├── README.md ├── XvideosViewer.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── fabriziochimienti.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── fabriziochimienti.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── XvideosViewer.xcscheme │ └── xcschememanagement.plist └── XvideosViewer ├── AppDelegate.swift ├── Assets.xcassets ├── App Icon & Top Shelf Image.brandassets │ ├── App Icon - Large.imagestack │ │ ├── Back.imagestacklayer │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Front.imagestacklayer │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ └── Middle.imagestacklayer │ │ │ ├── Content.imageset │ │ │ └── Contents.json │ │ │ └── Contents.json │ ├── App Icon - Small.imagestack │ │ ├── Back.imagestacklayer │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Front.imagestacklayer │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ └── Middle.imagestacklayer │ │ │ ├── Content.imageset │ │ │ └── Contents.json │ │ │ └── Contents.json │ ├── Contents.json │ ├── Top Shelf Image Wide.imageset │ │ └── Contents.json │ └── Top Shelf Image.imageset │ │ └── Contents.json ├── Contents.json └── LaunchImage.launchimage │ └── Contents.json ├── Base.lproj └── Main.storyboard ├── HomeSelectionController.swift ├── ImageNotfound.png ├── Info.plist ├── SeeVideo.swift ├── Utils.swift ├── VideoController.swift ├── ViewController.swift └── XvideosViewer.xcdatamodeld ├── .xccurrentversion └── XvideosViewer.xcdatamodel └── contents /README.md: -------------------------------------------------------------------------------- 1 | # Tvos-PornSitesViewer 2 | After youporn, now you could see, in only one app, the videos of youporn, xvideos, pornhub, redtube, tube8, ecc... I remember that it's only a simple application to test what tvOS can see and what you can't find in the tvOS store and that the app is (NC-17) 3 | 4 | 5 | I only wrap the website to find the url of preview, title and video. 6 | In the code there are some commets for future update, I try to add youjizz and xHamster but the use video in flv format that tvOS (version 9.2) can't read 7 | 8 | # Features 9 | 10 | * Search 11 | * Title and one image of preview for all video 12 | * When possible more than one streaming quality 13 | 14 | # Possible future features 15 | 16 | * Sorting 17 | * More sites 18 | * Loggin (diffucult but not impossible) 19 | 20 | # Wrapped sites 21 | 22 | [YouPorn](http://www.youporn.com "YouPorn") 23 | 24 | [Xvideos](http://www.xvideos.com "Xvideos") 25 | 26 | [Pornhub](http://www.pornhub.com "Pornhub") 27 | 28 | [RedTube](http://www.redtube.com "RedTube") 29 | 30 | [Tube8](http://www.tube8.com "Tube8") 31 | 32 | [Thumbzilla](http://www.thumbzilla.com "Thumbzilla") 33 | 34 | [XTube](http://www.xtube.com "XTube") 35 | -------------------------------------------------------------------------------- /XvideosViewer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D61BA0E61CA15B38007B03ED /* ImageNotfound.png in Resources */ = {isa = PBXBuildFile; fileRef = D61BA0E51CA15B38007B03ED /* ImageNotfound.png */; }; 11 | D61BA0E81CA179B4007B03ED /* HomeSelectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61BA0E71CA179B4007B03ED /* HomeSelectionController.swift */; }; 12 | D6DA094C1CA147E500FB521F /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DA094B1CA147E500FB521F /* Utils.swift */; }; 13 | D6F59A511C9FEA3B00788915 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F59A501C9FEA3B00788915 /* AppDelegate.swift */; }; 14 | D6F59A531C9FEA3B00788915 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F59A521C9FEA3B00788915 /* ViewController.swift */; }; 15 | D6F59A561C9FEA3B00788915 /* XvideosViewer.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = D6F59A541C9FEA3B00788915 /* XvideosViewer.xcdatamodeld */; }; 16 | D6F59A591C9FEA3B00788915 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6F59A571C9FEA3B00788915 /* Main.storyboard */; }; 17 | D6F59A5B1C9FEA3B00788915 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D6F59A5A1C9FEA3B00788915 /* Assets.xcassets */; }; 18 | D6F59A631C9FEEF700788915 /* VideoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F59A621C9FEEF700788915 /* VideoController.swift */; }; 19 | D6F59A651C9FEF1C00788915 /* SeeVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F59A641C9FEF1C00788915 /* SeeVideo.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | D61BA0E51CA15B38007B03ED /* ImageNotfound.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ImageNotfound.png; sourceTree = ""; }; 24 | D61BA0E71CA179B4007B03ED /* HomeSelectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeSelectionController.swift; sourceTree = ""; }; 25 | D6DA094B1CA147E500FB521F /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; 26 | D6F59A4D1C9FEA3B00788915 /* XvideosViewer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XvideosViewer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | D6F59A501C9FEA3B00788915 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 28 | D6F59A521C9FEA3B00788915 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 29 | D6F59A551C9FEA3B00788915 /* XvideosViewer.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = XvideosViewer.xcdatamodel; sourceTree = ""; }; 30 | D6F59A581C9FEA3B00788915 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 31 | D6F59A5A1C9FEA3B00788915 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 32 | D6F59A5C1C9FEA3B00788915 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | D6F59A621C9FEEF700788915 /* VideoController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoController.swift; sourceTree = ""; }; 34 | D6F59A641C9FEF1C00788915 /* SeeVideo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeeVideo.swift; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | D6F59A4A1C9FEA3B00788915 /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | D6F59A441C9FEA3B00788915 = { 49 | isa = PBXGroup; 50 | children = ( 51 | D6F59A4F1C9FEA3B00788915 /* XvideosViewer */, 52 | D6F59A4E1C9FEA3B00788915 /* Products */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | D6F59A4E1C9FEA3B00788915 /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | D6F59A4D1C9FEA3B00788915 /* XvideosViewer.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | D6F59A4F1C9FEA3B00788915 /* XvideosViewer */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | D61BA0E51CA15B38007B03ED /* ImageNotfound.png */, 68 | D6F59A501C9FEA3B00788915 /* AppDelegate.swift */, 69 | D6F59A521C9FEA3B00788915 /* ViewController.swift */, 70 | D6F59A571C9FEA3B00788915 /* Main.storyboard */, 71 | D6F59A5A1C9FEA3B00788915 /* Assets.xcassets */, 72 | D6F59A5C1C9FEA3B00788915 /* Info.plist */, 73 | D6F59A541C9FEA3B00788915 /* XvideosViewer.xcdatamodeld */, 74 | D6F59A621C9FEEF700788915 /* VideoController.swift */, 75 | D6F59A641C9FEF1C00788915 /* SeeVideo.swift */, 76 | D6DA094B1CA147E500FB521F /* Utils.swift */, 77 | D61BA0E71CA179B4007B03ED /* HomeSelectionController.swift */, 78 | ); 79 | path = XvideosViewer; 80 | sourceTree = ""; 81 | }; 82 | /* End PBXGroup section */ 83 | 84 | /* Begin PBXNativeTarget section */ 85 | D6F59A4C1C9FEA3B00788915 /* XvideosViewer */ = { 86 | isa = PBXNativeTarget; 87 | buildConfigurationList = D6F59A5F1C9FEA3B00788915 /* Build configuration list for PBXNativeTarget "XvideosViewer" */; 88 | buildPhases = ( 89 | D6F59A491C9FEA3B00788915 /* Sources */, 90 | D6F59A4A1C9FEA3B00788915 /* Frameworks */, 91 | D6F59A4B1C9FEA3B00788915 /* Resources */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = XvideosViewer; 98 | productName = XvideosViewer; 99 | productReference = D6F59A4D1C9FEA3B00788915 /* XvideosViewer.app */; 100 | productType = "com.apple.product-type.application"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | D6F59A451C9FEA3B00788915 /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastSwiftUpdateCheck = 0720; 109 | LastUpgradeCheck = 0820; 110 | ORGANIZATIONNAME = "fabrizio chimienti"; 111 | TargetAttributes = { 112 | D6F59A4C1C9FEA3B00788915 = { 113 | CreatedOnToolsVersion = 7.2.1; 114 | LastSwiftMigration = 0820; 115 | }; 116 | }; 117 | }; 118 | buildConfigurationList = D6F59A481C9FEA3B00788915 /* Build configuration list for PBXProject "XvideosViewer" */; 119 | compatibilityVersion = "Xcode 3.2"; 120 | developmentRegion = English; 121 | hasScannedForEncodings = 0; 122 | knownRegions = ( 123 | English, 124 | en, 125 | Base, 126 | ); 127 | mainGroup = D6F59A441C9FEA3B00788915; 128 | productRefGroup = D6F59A4E1C9FEA3B00788915 /* Products */; 129 | projectDirPath = ""; 130 | projectRoot = ""; 131 | targets = ( 132 | D6F59A4C1C9FEA3B00788915 /* XvideosViewer */, 133 | ); 134 | }; 135 | /* End PBXProject section */ 136 | 137 | /* Begin PBXResourcesBuildPhase section */ 138 | D6F59A4B1C9FEA3B00788915 /* Resources */ = { 139 | isa = PBXResourcesBuildPhase; 140 | buildActionMask = 2147483647; 141 | files = ( 142 | D61BA0E61CA15B38007B03ED /* ImageNotfound.png in Resources */, 143 | D6F59A5B1C9FEA3B00788915 /* Assets.xcassets in Resources */, 144 | D6F59A591C9FEA3B00788915 /* Main.storyboard in Resources */, 145 | ); 146 | runOnlyForDeploymentPostprocessing = 0; 147 | }; 148 | /* End PBXResourcesBuildPhase section */ 149 | 150 | /* Begin PBXSourcesBuildPhase section */ 151 | D6F59A491C9FEA3B00788915 /* Sources */ = { 152 | isa = PBXSourcesBuildPhase; 153 | buildActionMask = 2147483647; 154 | files = ( 155 | D6F59A651C9FEF1C00788915 /* SeeVideo.swift in Sources */, 156 | D6F59A531C9FEA3B00788915 /* ViewController.swift in Sources */, 157 | D6F59A561C9FEA3B00788915 /* XvideosViewer.xcdatamodeld in Sources */, 158 | D6F59A511C9FEA3B00788915 /* AppDelegate.swift in Sources */, 159 | D6F59A631C9FEEF700788915 /* VideoController.swift in Sources */, 160 | D6DA094C1CA147E500FB521F /* Utils.swift in Sources */, 161 | D61BA0E81CA179B4007B03ED /* HomeSelectionController.swift in Sources */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXSourcesBuildPhase section */ 166 | 167 | /* Begin PBXVariantGroup section */ 168 | D6F59A571C9FEA3B00788915 /* Main.storyboard */ = { 169 | isa = PBXVariantGroup; 170 | children = ( 171 | D6F59A581C9FEA3B00788915 /* Base */, 172 | ); 173 | name = Main.storyboard; 174 | sourceTree = ""; 175 | }; 176 | /* End PBXVariantGroup section */ 177 | 178 | /* Begin XCBuildConfiguration section */ 179 | D6F59A5D1C9FEA3B00788915 /* Debug */ = { 180 | isa = XCBuildConfiguration; 181 | buildSettings = { 182 | ALWAYS_SEARCH_USER_PATHS = NO; 183 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 184 | CLANG_CXX_LIBRARY = "libc++"; 185 | CLANG_ENABLE_MODULES = YES; 186 | CLANG_ENABLE_OBJC_ARC = YES; 187 | CLANG_WARN_BOOL_CONVERSION = YES; 188 | CLANG_WARN_CONSTANT_CONVERSION = YES; 189 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 190 | CLANG_WARN_EMPTY_BODY = YES; 191 | CLANG_WARN_ENUM_CONVERSION = YES; 192 | CLANG_WARN_INFINITE_RECURSION = YES; 193 | CLANG_WARN_INT_CONVERSION = YES; 194 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 195 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 196 | CLANG_WARN_UNREACHABLE_CODE = YES; 197 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 198 | COPY_PHASE_STRIP = NO; 199 | DEBUG_INFORMATION_FORMAT = dwarf; 200 | ENABLE_STRICT_OBJC_MSGSEND = YES; 201 | ENABLE_TESTABILITY = YES; 202 | GCC_C_LANGUAGE_STANDARD = gnu99; 203 | GCC_DYNAMIC_NO_PIC = NO; 204 | GCC_NO_COMMON_BLOCKS = YES; 205 | GCC_OPTIMIZATION_LEVEL = 0; 206 | GCC_PREPROCESSOR_DEFINITIONS = ( 207 | "DEBUG=1", 208 | "$(inherited)", 209 | ); 210 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 211 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 212 | GCC_WARN_UNDECLARED_SELECTOR = YES; 213 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 214 | GCC_WARN_UNUSED_FUNCTION = YES; 215 | GCC_WARN_UNUSED_VARIABLE = YES; 216 | MTL_ENABLE_DEBUG_INFO = YES; 217 | ONLY_ACTIVE_ARCH = YES; 218 | SDKROOT = appletvos; 219 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 220 | TARGETED_DEVICE_FAMILY = 3; 221 | TVOS_DEPLOYMENT_TARGET = 9.1; 222 | }; 223 | name = Debug; 224 | }; 225 | D6F59A5E1C9FEA3B00788915 /* Release */ = { 226 | isa = XCBuildConfiguration; 227 | buildSettings = { 228 | ALWAYS_SEARCH_USER_PATHS = NO; 229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 230 | CLANG_CXX_LIBRARY = "libc++"; 231 | CLANG_ENABLE_MODULES = YES; 232 | CLANG_ENABLE_OBJC_ARC = YES; 233 | CLANG_WARN_BOOL_CONVERSION = YES; 234 | CLANG_WARN_CONSTANT_CONVERSION = YES; 235 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 236 | CLANG_WARN_EMPTY_BODY = YES; 237 | CLANG_WARN_ENUM_CONVERSION = YES; 238 | CLANG_WARN_INFINITE_RECURSION = YES; 239 | CLANG_WARN_INT_CONVERSION = YES; 240 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 241 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 242 | CLANG_WARN_UNREACHABLE_CODE = YES; 243 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 244 | COPY_PHASE_STRIP = NO; 245 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 246 | ENABLE_NS_ASSERTIONS = NO; 247 | ENABLE_STRICT_OBJC_MSGSEND = YES; 248 | GCC_C_LANGUAGE_STANDARD = gnu99; 249 | GCC_NO_COMMON_BLOCKS = YES; 250 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 251 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 252 | GCC_WARN_UNDECLARED_SELECTOR = YES; 253 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 254 | GCC_WARN_UNUSED_FUNCTION = YES; 255 | GCC_WARN_UNUSED_VARIABLE = YES; 256 | MTL_ENABLE_DEBUG_INFO = NO; 257 | SDKROOT = appletvos; 258 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 259 | TARGETED_DEVICE_FAMILY = 3; 260 | TVOS_DEPLOYMENT_TARGET = 9.1; 261 | VALIDATE_PRODUCT = YES; 262 | }; 263 | name = Release; 264 | }; 265 | D6F59A601C9FEA3B00788915 /* Debug */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; 269 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 270 | INFOPLIST_FILE = XvideosViewer/Info.plist; 271 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 272 | PRODUCT_BUNDLE_IDENTIFIER = com.fabriziochimienti.XvideosViewer; 273 | PRODUCT_NAME = "$(TARGET_NAME)"; 274 | SWIFT_VERSION = 5.0; 275 | }; 276 | name = Debug; 277 | }; 278 | D6F59A611C9FEA3B00788915 /* Release */ = { 279 | isa = XCBuildConfiguration; 280 | buildSettings = { 281 | ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; 282 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 283 | INFOPLIST_FILE = XvideosViewer/Info.plist; 284 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 285 | PRODUCT_BUNDLE_IDENTIFIER = com.fabriziochimienti.XvideosViewer; 286 | PRODUCT_NAME = "$(TARGET_NAME)"; 287 | SWIFT_VERSION = 5.0; 288 | }; 289 | name = Release; 290 | }; 291 | /* End XCBuildConfiguration section */ 292 | 293 | /* Begin XCConfigurationList section */ 294 | D6F59A481C9FEA3B00788915 /* Build configuration list for PBXProject "XvideosViewer" */ = { 295 | isa = XCConfigurationList; 296 | buildConfigurations = ( 297 | D6F59A5D1C9FEA3B00788915 /* Debug */, 298 | D6F59A5E1C9FEA3B00788915 /* Release */, 299 | ); 300 | defaultConfigurationIsVisible = 0; 301 | defaultConfigurationName = Release; 302 | }; 303 | D6F59A5F1C9FEA3B00788915 /* Build configuration list for PBXNativeTarget "XvideosViewer" */ = { 304 | isa = XCConfigurationList; 305 | buildConfigurations = ( 306 | D6F59A601C9FEA3B00788915 /* Debug */, 307 | D6F59A611C9FEA3B00788915 /* Release */, 308 | ); 309 | defaultConfigurationIsVisible = 0; 310 | defaultConfigurationName = Release; 311 | }; 312 | /* End XCConfigurationList section */ 313 | 314 | /* Begin XCVersionGroup section */ 315 | D6F59A541C9FEA3B00788915 /* XvideosViewer.xcdatamodeld */ = { 316 | isa = XCVersionGroup; 317 | children = ( 318 | D6F59A551C9FEA3B00788915 /* XvideosViewer.xcdatamodel */, 319 | ); 320 | currentVersion = D6F59A551C9FEA3B00788915 /* XvideosViewer.xcdatamodel */; 321 | path = XvideosViewer.xcdatamodeld; 322 | sourceTree = ""; 323 | versionGroupType = wrapper.xcdatamodel; 324 | }; 325 | /* End XCVersionGroup section */ 326 | }; 327 | rootObject = D6F59A451C9FEA3B00788915 /* Project object */; 328 | } 329 | -------------------------------------------------------------------------------- /XvideosViewer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XvideosViewer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /XvideosViewer.xcodeproj/project.xcworkspace/xcuserdata/fabriziochimienti.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimiko88/Tvos-PornSitesViewer/8748cb1477429704cdb2d6bfc8ea93540c8b82cc/XvideosViewer.xcodeproj/project.xcworkspace/xcuserdata/fabriziochimienti.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /XvideosViewer.xcodeproj/xcuserdata/fabriziochimienti.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 22 | 23 | 24 | 26 | 39 | 40 | 41 | 43 | 55 | 56 | 57 | 59 | 71 | 72 | 86 | 87 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /XvideosViewer.xcodeproj/xcuserdata/fabriziochimienti.xcuserdatad/xcschemes/XvideosViewer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /XvideosViewer.xcodeproj/xcuserdata/fabriziochimienti.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | XvideosViewer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D6F59A4C1C9FEA3B00788915 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /XvideosViewer/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // XvideosViewer 4 | // 5 | // Created by fabrizio chimienti on 21/03/16. 6 | // Copyright © 2016 fabrizio chimienti. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreData 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | 18 | 19 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 20 | // Override point for customization after application launch. 21 | return true 22 | } 23 | 24 | func applicationWillResignActive(_ application: UIApplication) { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 27 | } 28 | 29 | func applicationDidEnterBackground(_ application: UIApplication) { 30 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 31 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 32 | } 33 | 34 | func applicationWillEnterForeground(_ application: UIApplication) { 35 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 36 | } 37 | 38 | func applicationDidBecomeActive(_ application: UIApplication) { 39 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 40 | } 41 | 42 | func applicationWillTerminate(_ application: UIApplication) { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | // Saves changes in the application's managed object context before the application terminates. 45 | self.saveContext() 46 | } 47 | 48 | // MARK: - Core Data stack 49 | 50 | lazy var applicationCachesDirectory: URL = { 51 | // The directory the application uses to store the Core Data store file. This code uses a directory named "com.fabriziochimienti.XvideosViewer" in the application's caches Application Support directory. 52 | let urls = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask) 53 | return urls[urls.count-1] 54 | }() 55 | 56 | lazy var managedObjectModel: NSManagedObjectModel = { 57 | // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model. 58 | let modelURL = Bundle.main.url(forResource: "XvideosViewer", withExtension: "momd")! 59 | return NSManagedObjectModel(contentsOf: modelURL)! 60 | }() 61 | 62 | lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = { 63 | // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. 64 | // Create the coordinator and store 65 | let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) 66 | let url = self.applicationCachesDirectory.appendingPathComponent("SingleViewCoreData.sqlite") 67 | var failureReason = "There was an error creating or loading the application's saved data." 68 | do { 69 | try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil) 70 | } catch { 71 | // Report any error we got. 72 | var dict = [String: AnyObject]() 73 | dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject? 74 | dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject? 75 | 76 | dict[NSUnderlyingErrorKey] = error as NSError 77 | let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) 78 | // Replace this with code to handle the error appropriately. 79 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 80 | NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)") 81 | abort() 82 | } 83 | 84 | return coordinator 85 | }() 86 | 87 | lazy var managedObjectContext: NSManagedObjectContext = { 88 | // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail. 89 | let coordinator = self.persistentStoreCoordinator 90 | var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) 91 | managedObjectContext.persistentStoreCoordinator = coordinator 92 | return managedObjectContext 93 | }() 94 | 95 | // MARK: - Core Data Saving support 96 | 97 | func saveContext () { 98 | if managedObjectContext.hasChanges { 99 | do { 100 | try managedObjectContext.save() 101 | } catch { 102 | // Replace this implementation with code to handle the error appropriately. 103 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 104 | let nserror = error as NSError 105 | NSLog("Unresolved error \(nserror), \(nserror.userInfo)") 106 | abort() 107 | } 108 | } 109 | } 110 | 111 | } 112 | 113 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "layers" : [ 3 | { 4 | "filename" : "Front.imagestacklayer" 5 | }, 6 | { 7 | "filename" : "Middle.imagestacklayer" 8 | }, 9 | { 10 | "filename" : "Back.imagestacklayer" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "layers" : [ 3 | { 4 | "filename" : "Front.imagestacklayer" 5 | }, 6 | { 7 | "filename" : "Middle.imagestacklayer" 8 | }, 9 | { 10 | "filename" : "Back.imagestacklayer" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "filename" : "App Icon - Large.imagestack", 5 | "idiom" : "tv", 6 | "role" : "primary-app-icon", 7 | "size" : "1280x768" 8 | }, 9 | { 10 | "filename" : "App Icon - Small.imagestack", 11 | "idiom" : "tv", 12 | "role" : "primary-app-icon", 13 | "size" : "400x240" 14 | }, 15 | { 16 | "filename" : "Top Shelf Image Wide.imageset", 17 | "idiom" : "tv", 18 | "role" : "top-shelf-image-wide", 19 | "size" : "2320x720" 20 | }, 21 | { 22 | "filename" : "Top Shelf Image.imageset", 23 | "idiom" : "tv", 24 | "role" : "top-shelf-image", 25 | "size" : "1920x720" 26 | } 27 | ], 28 | "info" : { 29 | "author" : "xcode", 30 | "version" : 1 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XvideosViewer/Assets.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "tv", 6 | "minimum-system-version" : "11.0", 7 | "orientation" : "landscape", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "extent" : "full-screen", 12 | "idiom" : "tv", 13 | "minimum-system-version" : "9.0", 14 | "orientation" : "landscape", 15 | "scale" : "1x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /XvideosViewer/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /XvideosViewer/HomeSelectionController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeSelectionController.swift 3 | // XvideosViewer 4 | // 5 | // Created by kimiko88 on 22/03/16. 6 | // Copyright © 2016 kimiko88. All rights reserved. 7 | // 8 | // let muturl = NSMutableURLRequest(URL: NSURL(string:tempurl)!) 9 | // 10 | // muturl.setValue("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36", forHTTPHeaderField: "User-Agent") 11 | //let url = muturl as NSURLRequest 12 | 13 | import Foundation 14 | import UIKit 15 | 16 | class Video{ 17 | var Link: String 18 | var ImageLink: String 19 | var Title: String 20 | init(link: String, imageLink: String, title: String) 21 | { 22 | Link = link 23 | ImageLink = imageLink 24 | Title = title 25 | } 26 | } 27 | 28 | 29 | extension Array where Element : Equatable { 30 | var unique: [Element] { 31 | var uniqueValues: [Element] = [] 32 | forEach { item in 33 | if !uniqueValues.contains(item) { 34 | uniqueValues += [item] 35 | } 36 | } 37 | return uniqueValues 38 | } 39 | } 40 | 41 | class HomeSelectionController: UIViewController { 42 | 43 | var videos = [Video]() 44 | var actualPage = 0; 45 | var bounds = UIScreen.main.bounds 46 | var scroll = UIScrollView() 47 | var field = UITextField() 48 | var isSearch: Bool = false 49 | var isSorted: Bool = false 50 | var selectedSort: String = "rating" 51 | var selectedSite: String = "" 52 | var baseURL: URL! 53 | 54 | override func viewDidLoad() { 55 | super.viewDidLoad() 56 | self.view = self.scroll; 57 | self.scroll.backgroundColor = UIColor.black 58 | showPage(actualPage) 59 | } 60 | 61 | 62 | func showPage(_ actualPage: Int){ 63 | videos = [Video]() 64 | self.isSearch = false 65 | let subViews = self.scroll.subviews 66 | for subview in subViews{ 67 | subview.removeFromSuperview() 68 | } 69 | if(selectedSite == "YouPorn") 70 | { 71 | let url = URL(string: "http://www.youporn.com/?page=\(actualPage)")! 72 | YouPornCharge(url) 73 | } 74 | if(selectedSite == "Xvideos") 75 | { 76 | var tempurl = "http://www.xvideos.com/" 77 | if(actualPage != 0) 78 | { 79 | tempurl = "http://www.xvideos.com/new/\(actualPage)" 80 | } 81 | let url = URL(string:tempurl)! 82 | XvideosCharge(url) 83 | } 84 | if(selectedSite == "Pornhub") 85 | { 86 | var tempurl = "http://www.pornhub.com" 87 | if(actualPage != 0) 88 | { 89 | tempurl = "http://www.pornhub.com/video?page=\(actualPage)" 90 | } 91 | let url = URL(string:tempurl)! 92 | PornhubCharge(url) 93 | } 94 | if(selectedSite == "RedTube") 95 | { 96 | var tempurl = "http://www.redtube.com" 97 | if(actualPage != 0) 98 | { 99 | tempurl = "http://www.redtube.com?page=\(actualPage)" 100 | } 101 | let url = URL(string:tempurl)! 102 | RedTubeCharge(url) 103 | } 104 | if(selectedSite == "Tube8") 105 | { 106 | var tempurl = "http://www.tube8.com" 107 | if(actualPage != 0) 108 | { 109 | tempurl = "http://www.tube8.com/latest/page/\(actualPage)/" 110 | } 111 | let url = URL(string:tempurl)! 112 | Tube8Charge(url) 113 | } 114 | if(selectedSite == "PornMD") 115 | { 116 | let tempurl = "http://www.pornmd.com" 117 | 118 | let url = URL(string: tempurl)! 119 | PornMDCharge(url) 120 | } 121 | if(selectedSite == "Thumbzilla") 122 | { 123 | var tempurl = "http://www.thumbzilla.com" 124 | if(actualPage != 0) 125 | { 126 | tempurl = "http://www.thumbzilla.com/?page=\(actualPage + 1)" 127 | } 128 | let url = URL(string:tempurl)! 129 | ThumbzillaCharge(url) 130 | } 131 | if(selectedSite == "XTube") 132 | { 133 | var tempurl = "http://www.xtube.com" 134 | if(actualPage != 0) 135 | { 136 | tempurl = "http://www.xtube.com/video/\(actualPage + 1)" 137 | } 138 | let url = URL(string:tempurl)! 139 | XTubeCharge(url) 140 | } 141 | // if(selectedSite == "YouJizz") 142 | // { 143 | // var tempurl = "http://www.youjizz.com" 144 | // if(actualPage != 0) 145 | // { 146 | // tempurl = "http://www.youjizz.com/page/\(actualPage + 1).html" 147 | // } 148 | // let url = NSURL(string:tempurl)! 149 | // YouJizzCharge(url) 150 | // } 151 | 152 | } 153 | 154 | func YouPornCharge(_ url: URL) { 155 | // let url = NSURL(string: "http://www.youporn.com/?page=\(actualPage)")! 156 | let task = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in 157 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 158 | let strin = String(stringa) 159 | let splitted = strin.split{$0 == " "}.map(String.init) 160 | 161 | for var i in 0 ..< splitted.count 162 | { 163 | let oo = splitted[i] 164 | if (oo.range(of: "href=\"/watch/") != nil && splitted[i + 1].range(of: "class='video-box-image'") != nil){ 165 | let link = oo.replacingOccurrences(of: "href=\"",with: "http://www.youporn.com").replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "\">", with: "") 166 | var tempTitle = "" 167 | var start = false 168 | i += 1 169 | while((splitted[i].range(of: "\n")) == nil) 170 | { 171 | i += 1 172 | if(splitted[i].range(of: "title=\"") != nil){ 173 | start = true 174 | } 175 | if(start){ 176 | tempTitle += " " + splitted[i] 177 | } 178 | } 179 | let title = tempTitle.replacingOccurrences(of: " title=\"", with: "").replacingOccurrences(of: "\">\n 0){ 199 | self.previousButton(i) 200 | i += 1 201 | } 202 | 203 | self.homeButton(i) 204 | i += 1 205 | 206 | self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 207 | self.scroll.isScrollEnabled = true 208 | } 209 | }) 210 | task.resume() 211 | 212 | } 213 | 214 | func XvideosCharge(_ url: URL){ 215 | let task = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in 216 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 217 | let imageLink = Utils.GetStringsByRegularExpression(stringa, regularexp: "]*?\\s+)?src=\"http://img\\-([^\"]*)\"") 218 | let titleAndHref = Utils.GetStringsByRegularExpression(stringa, regularexp: " 0){ 245 | self.previousButton(i) 246 | i += 1 247 | } 248 | 249 | self.homeButton(i) 250 | i += 1 251 | 252 | self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 253 | self.scroll.isScrollEnabled = true 254 | } 255 | }) 256 | task.resume() 257 | } 258 | 259 | func PornhubCharge(_ url: URL){ 260 | let task = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in 261 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)!.replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: "\t", with: "") 262 | let imageLink = Utils.GetStringsByRegularExpression(stringa as NSString, regularexp: 263 | "]*>") 264 | let titleAndHref = Utils.GetStringsByRegularExpression(stringa as NSString, regularexp: 265 | "class=\"title\">]*?\\s+)?href=\"/view_video.php?([^\"]*)\"?\\stitle=\"([^\"]*)\"") 266 | print(imageLink.count) 267 | print(titleAndHref.count) 268 | if(imageLink.count == titleAndHref.count) 269 | { 270 | for i in 0 ..< titleAndHref.count 271 | { 272 | let imglinkTemp = Utils.GetStringsByRegularExpression(imageLink[i] as NSString,regularexp: "data-mediumthumb=\"[^\"]*\"")[0].replacingOccurrences(of: "data-mediumthumb=\"", with: "").replacingOccurrences(of: "\"", with: "") 273 | let href = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "href=\"[^\"]*\"")[0].replacingOccurrences(of: "href=\"",with: "http://www.pornhub.com").replacingOccurrences(of: "\"", with: "") 274 | let title = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "title=\"[^\"]*\"")[0].replacingOccurrences(of: "title=\"",with: "").replacingOccurrences(of: "\"", with: "").removingPercentEncoding 275 | let video = Video(link: href, imageLink: imglinkTemp, title: title!) 276 | self.videos.append(video) 277 | } 278 | } 279 | else{ 280 | //refresh button 281 | } 282 | DispatchQueue.main.async{ 283 | var i = 1; 284 | self.TextField(i) 285 | i += 3 286 | self.searchButton(i) 287 | i += 1 288 | for video in self.videos{ 289 | self.chargeImageAsync(video.ImageLink,index :i, video: video) 290 | i += 1; 291 | } 292 | self.nextButton(i) 293 | i += 1; 294 | if(self.actualPage > 0){ 295 | self.previousButton(i) 296 | i += 1 297 | } 298 | 299 | self.homeButton(i) 300 | i += 1 301 | 302 | self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 303 | self.scroll.isScrollEnabled = true 304 | } 305 | }) 306 | task.resume() 307 | } 308 | 309 | 310 | func RedTubeCharge(_ url: URL){ 311 | let task = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in 312 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 313 | let imageLink = Utils.GetStringsByRegularExpression(stringa, regularexp: "span>(\\s*)]*?\\s+)?src=\"?([^\"]*)\"?\\s") 314 | let titleAndHref = Utils.GetStringsByRegularExpression(stringa, regularexp: "]*?\\s+)?class=\"video-thumb([^\"]*)\"?") 315 | print(imageLink) 316 | print(titleAndHref) 317 | print(imageLink.count) 318 | print(titleAndHref.count) 319 | if(imageLink.count == titleAndHref.count) 320 | { 321 | for i in 0 ..< titleAndHref.count 322 | { 323 | let imglinkTemp = Utils.GetStringsByRegularExpression(imageLink[i] as NSString, regularexp: "data-src=\"[^\"]*\"")[0].replacingOccurrences(of: "data-src=\"",with: "").replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "//", with: "http://") 324 | let href = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "href=\"[^\"]*\"")[0].replacingOccurrences(of: "href=\"",with: "http://www.redtube.com").replacingOccurrences(of: "\"", with: "") 325 | let title = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "title=\"[^\"]*\"")[0].replacingOccurrences(of: "title=\"",with: "").replacingOccurrences(of: "\"", with: "").removingPercentEncoding 326 | let video = Video(link: href, imageLink: imglinkTemp, title: title!) 327 | self.videos.append(video) 328 | } 329 | } 330 | else{ 331 | //refresh button 332 | } 333 | DispatchQueue.main.async{ 334 | var i = 1; 335 | self.TextField(i) 336 | i += 3 337 | self.searchButton(i) 338 | i += 1 339 | for video in self.videos{ 340 | self.chargeImageAsync(video.ImageLink,index :i, video: video) 341 | i += 1; 342 | } 343 | self.nextButton(i) 344 | i += 1; 345 | if(self.actualPage > 0){ 346 | self.previousButton(i) 347 | i += 1 348 | } 349 | 350 | self.homeButton(i) 351 | i += 1 352 | 353 | self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 354 | self.scroll.isScrollEnabled = true 355 | } 356 | }) 357 | task.resume() 358 | } 359 | 360 | 361 | func Tube8Charge(_ url: URL){ 362 | let task = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in 363 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 364 | let imageLink = Utils.GetStringsByRegularExpression(stringa, regularexp: "class=\"videoThumbs\"\\s+(?:[^>]*?\\s+)?src=\"?([^\"]*)\"?") 365 | let titleAndHref = Utils.GetStringsByRegularExpression(stringa, regularexp: "video_title\">(\\s*)]*?\\s+)?href=\"?([^\"]*)\"?\\stitle=\"?([^\"]*)\"?") 366 | print(imageLink) 367 | print(titleAndHref) 368 | print(imageLink.count) 369 | print(titleAndHref.count) 370 | if(imageLink.count == titleAndHref.count) 371 | { 372 | for i in 0 ..< titleAndHref.count 373 | { 374 | let imglinkTemp = Utils.GetStringsByRegularExpression(imageLink[i] as NSString, regularexp: "src=\"?([^\"]*)\"?")[0].replacingOccurrences(of: "src=\"",with: "").replacingOccurrences(of: "\"", with: "") 375 | let href = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "href=\"[^\"]*\"")[0].replacingOccurrences(of: "href=\"",with: "").replacingOccurrences(of: "\"", with: "") 376 | let title = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "title=\"[^\"]*\"")[0].replacingOccurrences(of: "title=\"",with: "").replacingOccurrences(of: "\"", with: "").removingPercentEncoding 377 | let video = Video(link: href, imageLink: imglinkTemp, title: title!) 378 | self.videos.append(video) 379 | } 380 | } 381 | else{ 382 | //refresh button 383 | } 384 | DispatchQueue.main.async{ 385 | var i = 1; 386 | self.TextField(i) 387 | i += 3 388 | self.searchButton(i) 389 | i += 1 390 | for video in self.videos{ 391 | self.chargeImageAsync(video.ImageLink,index :i, video: video) 392 | i += 1; 393 | } 394 | self.nextButton(i) 395 | i += 1; 396 | if(self.actualPage > 0){ 397 | self.previousButton(i) 398 | i += 1 399 | } 400 | 401 | self.homeButton(i) 402 | i += 1 403 | 404 | self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 405 | self.scroll.isScrollEnabled = true 406 | } 407 | }) 408 | task.resume() 409 | } 410 | 411 | 412 | func ThumbzillaCharge(_ url: URL){ 413 | let task = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in 414 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 415 | 416 | let imageLink = Utils.GetStringsByRegularExpression(stringa, regularexp: "data-original=\"?([^\"]*)\"?") 417 | let href = Utils.GetStringsByRegularExpression(stringa, regularexp: "js-thumb\"\\shref=\"[^\"]*\"") 418 | let title = Utils.GetStringsByRegularExpression(stringa, regularexp: "info\">(\\s*)]*?\\s+)?class=\"title\">(.*?)<") 419 | 420 | let uniqueimage = imageLink.unique 421 | print(uniqueimage.count) 422 | if(uniqueimage.count == title.count && title.count == href.count) 423 | { 424 | for i in 0 ..< href.count 425 | { 426 | let imglinkTemp = uniqueimage[i].replacingOccurrences(of: "data-original=\"",with: "").replacingOccurrences(of: "\"", with: "") 427 | let href = Utils.GetStringsByRegularExpression(href[i] as NSString, regularexp: "href=\"[^\"]*\"")[0].replacingOccurrences(of: "href=\"",with: "http://www.thumbzilla.com").replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: ">", with: ">") 428 | let title = Utils.GetStringsByRegularExpression(title[i] as NSString, regularexp: ">(.*?)<")[0].replacingOccurrences(of: "title=\"",with: "").replacingOccurrences(of: "<", with: "").replacingOccurrences(of: ">", with: "").removingPercentEncoding 429 | let video = Video(link: href, imageLink: imglinkTemp, title: title!) 430 | self.videos.append(video) 431 | } 432 | } 433 | else{ 434 | //refresh button 435 | } 436 | DispatchQueue.main.async{ 437 | var i = 1; 438 | self.TextField(i) 439 | i += 3 440 | self.searchButton(i) 441 | i += 1 442 | for video in self.videos{ 443 | self.chargeImageAsync(video.ImageLink,index :i, video: video) 444 | i += 1; 445 | } 446 | self.nextButton(i) 447 | i += 1; 448 | if(self.actualPage > 0){ 449 | self.previousButton(i) 450 | i += 1 451 | } 452 | 453 | self.homeButton(i) 454 | i += 1 455 | 456 | self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 457 | self.scroll.isScrollEnabled = true 458 | } 459 | }) 460 | task.resume() 461 | } 462 | 463 | 464 | func XTubeCharge(_ url: URL){ 465 | let task = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in 466 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 467 | let imageLink = Utils.GetStringsByRegularExpression(stringa, regularexp: "video\"(\\s*)>(\\s*)<(.*?)>") 468 | let titleAndHref = Utils.GetStringsByRegularExpression(stringa, regularexp: "") 469 | print(imageLink) 470 | print(titleAndHref) 471 | print(imageLink.count) 472 | print(titleAndHref.count) 473 | if(imageLink.count == titleAndHref.count) 474 | { 475 | for i in 0 ..< titleAndHref.count 476 | { 477 | var imglinkTemp = Utils.GetStringsByRegularExpression(imageLink[i] as NSString, regularexp: "src=\"?([^\"]*)\"?")[0].replacingOccurrences(of: "src=\"",with: "").replacingOccurrences(of: "\"", with: "") 478 | if(imageLink[i].contains("placeholder")) 479 | { 480 | imglinkTemp = Utils.GetStringsByRegularExpression(imageLink[i] as NSString, regularexp: "data-lazySrc=\"?([^\"]*)\"?")[0].replacingOccurrences(of: "data-lazySrc=\"",with: "").replacingOccurrences(of: "\"", with: "") 481 | } 482 | let href = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "href=\"[^\"]*\"")[0].replacingOccurrences(of: "href=\"",with: "http://www.xtube.com").replacingOccurrences(of: "\"", with: "") 483 | let title = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "title=\"[^\"]*\"")[0].replacingOccurrences(of: "title=\"",with: "").replacingOccurrences(of: "\"", with: "").removingPercentEncoding 484 | let video = Video(link: href, imageLink: imglinkTemp, title: title!) 485 | self.videos.append(video) 486 | } 487 | } 488 | else{ 489 | //refresh button 490 | } 491 | DispatchQueue.main.async{ 492 | var i = 1; 493 | // self.TextField(i) 494 | i += 3 495 | // self.searchButton(i) 496 | i += 1 497 | for video in self.videos{ 498 | self.chargeImageAsync(video.ImageLink,index :i, video: video) 499 | i += 1; 500 | } 501 | self.nextButton(i) 502 | i += 1; 503 | if(self.actualPage > 0){ 504 | self.previousButton(i) 505 | i += 1 506 | } 507 | 508 | self.homeButton(i) 509 | i += 1 510 | 511 | self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 512 | self.scroll.isScrollEnabled = true 513 | } 514 | }) 515 | task.resume() 516 | } 517 | func PornMDCharge(_ url: URL){ 518 | if(url == URL(string: "http://www.pornmd.com")) 519 | { 520 | DispatchQueue.main.async{ 521 | var i = 1; 522 | self.TextField(i) 523 | i += 3 524 | self.searchButton(i) 525 | i += 1 526 | // for video in self.videos{ 527 | // self.chargeImageAsync(video.ImageLink,index :i, video: video) 528 | // i += 1; 529 | // } 530 | // self.nextButton(i) 531 | // i += 1; 532 | // if(self.actualPage > 0){ 533 | // self.previousButton(i) 534 | // i += 1 535 | // } 536 | // 537 | // self.homeButton(i) 538 | // i += 1 539 | 540 | self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 541 | self.scroll.isScrollEnabled = true 542 | } 543 | }else{ 544 | let task = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in 545 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 546 | var imageLink = Utils.GetStringsByRegularExpression(stringa, regularexp: "video\"(\\s*)>(\\s*)<(.*?)>") 547 | var titleAndHref = Utils.GetStringsByRegularExpression(stringa, regularexp: "") 548 | print(imageLink) 549 | print(titleAndHref) 550 | print(imageLink.count) 551 | print(titleAndHref.count) 552 | if(imageLink.count == titleAndHref.count) 553 | { 554 | for i in 0 ..< titleAndHref.count 555 | { 556 | var imglinkTemp = Utils.GetStringsByRegularExpression(imageLink[i] as NSString, regularexp: "src=\"?([^\"]*)\"?")[0].replacingOccurrences(of: "src=\"",with: "").replacingOccurrences(of: "\"", with: "") 557 | if(imageLink[i].contains("placeholder")) 558 | { 559 | imglinkTemp = Utils.GetStringsByRegularExpression(imageLink[i] as NSString, regularexp: "data-lazySrc=\"?([^\"]*)\"?")[0].replacingOccurrences(of: "data-lazySrc=\"",with: "").replacingOccurrences(of: "\"", with: "") 560 | } 561 | let href = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "href=\"[^\"]*\"")[0].replacingOccurrences(of: "href=\"",with: "http://www.xtube.com").replacingOccurrences(of: "\"", with: "") 562 | let title = Utils.GetStringsByRegularExpression(titleAndHref[i] as NSString, regularexp: "title=\"[^\"]*\"")[0].replacingOccurrences(of: "title=\"",with: "").replacingOccurrences(of: "\"", with: "").removingPercentEncoding 563 | let video = Video(link: href, imageLink: imglinkTemp, title: title!) 564 | self.videos.append(video) 565 | } 566 | } 567 | else{ 568 | //refresh button 569 | } 570 | DispatchQueue.main.async{ 571 | var i = 1; 572 | // self.TextField(i) 573 | i += 3 574 | // self.searchButton(i) 575 | i += 1 576 | for video in self.videos{ 577 | self.chargeImageAsync(video.ImageLink,index :i, video: video) 578 | i += 1; 579 | } 580 | self.nextButton(i) 581 | i += 1; 582 | if(self.actualPage > 0){ 583 | self.previousButton(i) 584 | i += 1 585 | } 586 | 587 | self.homeButton(i) 588 | i += 1 589 | 590 | self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 591 | self.scroll.isScrollEnabled = true 592 | } 593 | }) 594 | task.resume() 595 | } 596 | } 597 | 598 | // func YouJizzCharge(url: NSURL){ 599 | // let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in 600 | // let stringa = NSString(data: data!, encoding: NSUTF8StringEncoding)! 601 | // print(stringa) 602 | // let imageLink = Utils.GetStringsByRegularExpression(stringa, regularexp: "data-original=\"[^\"]*\"") 603 | // var href = Utils.GetStringsByRegularExpression(stringa, regularexp: "frame\"(.*?)href=[\"|'](.*?)[\"|']") 604 | // var title = Utils.GetStringsByRegularExpression(stringa, regularexp: "title1\"(.*?)<") 605 | // print(imageLink) 606 | // print(href) 607 | // print(title) 608 | // print(imageLink.count) 609 | // print(href.count) 610 | // print(title.count) 611 | //// let uniqueimage = imageLink.unique 612 | //// print(uniqueimage.count) 613 | // if(imageLink.count == title.count && title.count == href.count) 614 | // { 615 | // for i in 0 ..< href.count 616 | // { 617 | // print(imageLink[i]) 618 | // let imglinkTemp = imageLink[i].stringByReplacingOccurrencesOfString("data-original=\"",withString: "").stringByReplacingOccurrencesOfString("\"", withString: "") 619 | // print(imglinkTemp) 620 | // print(href[i]) 621 | // let href = Utils.GetStringsByRegularExpression(href[i], regularexp: "href=[\"|'][^\"|^']*[\"|']")[0].stringByReplacingOccurrencesOfString("href='",withString: "http://www.youjizz.com").stringByReplacingOccurrencesOfString("\"", withString: "").stringByReplacingOccurrencesOfString("'", withString: "").stringByReplacingOccurrencesOfString(">", withString: ">") 622 | // print(href) 623 | // print(title[i]) 624 | // let title = Utils.GetStringsByRegularExpression(title[i], regularexp: ">(.*?)<")[0].stringByReplacingOccurrencesOfString("title=\"",withString: "").stringByReplacingOccurrencesOfString("<", withString: "").stringByReplacingOccurrencesOfString(">", withString: "").stringByRemovingPercentEncoding 625 | // print(title) 626 | // let video = Video(link: href, imageLink: imglinkTemp, title: title!) 627 | // self.videos.append(video) 628 | // } 629 | // } 630 | // else{ 631 | // //refresh button 632 | // } 633 | // dispatch_async(dispatch_get_main_queue()){ 634 | // var i = 1; 635 | // self.TextField(i) 636 | // i += 3 637 | // self.searchButton(i) 638 | // i += 1 639 | // for video in self.videos{ 640 | // self.chargeImageAsync(video.ImageLink,index :i, video: video) 641 | // i += 1; 642 | // } 643 | // self.nextButton(i) 644 | // i += 1; 645 | // if(self.actualPage > 0){ 646 | // self.previousButton(i) 647 | // i += 1 648 | // } 649 | // 650 | // self.homeButton(i) 651 | // i += 1 652 | // 653 | // self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 654 | // self.scroll.scrollEnabled = true 655 | // } 656 | // } 657 | // task.resume() 658 | // } 659 | 660 | 661 | func searchText(_ textToSearch: String){ 662 | videos = [Video]() 663 | let subViews = self.scroll.subviews 664 | for subview in subViews{ 665 | subview.removeFromSuperview() 666 | } 667 | self.isSearch = true 668 | self.selectedSort = "relevance" 669 | if(selectedSite == "YouPorn") 670 | { 671 | let url = URL(string: "http://www.youporn.com/search/?query=\(textToSearch.replacingOccurrences(of: " ", with: "+"))&page=\(actualPage + 1)")! 672 | YouPornCharge(url) 673 | } 674 | if(selectedSite == "Xvideos") 675 | { 676 | let url = URL(string: "http://www.xvideos.com/?k=\(textToSearch.replacingOccurrences(of: " ", with: "+"))&p=\(actualPage)")! 677 | XvideosCharge(url) 678 | } 679 | if(selectedSite == "Pornhub") 680 | { 681 | let tempurl = "http://www.pornhub.com/video/search?search=?query=\(textToSearch.replacingOccurrences(of: " ", with: "+"))&page=\(actualPage + 1)" 682 | let url = URL(string:tempurl)! 683 | PornhubCharge(url) 684 | } 685 | if(selectedSite == "RedTube"){ 686 | let tempurl = "http://www.redtube.com/?search=\(textToSearch.replacingOccurrences(of: " ", with: "+"))&page=\(actualPage + 1)" 687 | let url = URL(string:tempurl)! 688 | RedTubeCharge(url) 689 | } 690 | if(selectedSite == "Tube8") 691 | { 692 | let tempurl = "http://www.tube8.com/searches.html?q=\(textToSearch.replacingOccurrences(of: " ", with: "+"))&page=\(actualPage + 1)" 693 | let url = URL(string:tempurl)! 694 | Tube8Charge(url) 695 | } 696 | // if(selectedSite == "PornMD") 697 | // { 698 | // let tempurl = "http://www.pornmd.com/straight/\(textToSearch.stringByReplacingOccurrencesOfString(" ", withString: "+"))&page=\(actualPage + 1)" 699 | // } 700 | if(selectedSite == "Thumbzilla") 701 | { 702 | let tempurl = "http://www.thumbzilla.com/video/search?q=\(textToSearch.replacingOccurrences(of: " ", with: "+"))&page=\(actualPage + 1)" 703 | let url = URL(string:tempurl)! 704 | ThumbzillaCharge(url) 705 | } 706 | 707 | // if(selectedSite == "YouJizz") 708 | // { 709 | // let tempurl = "http://www.youjizz.com/search/\(textToSearch.stringByReplacingOccurrencesOfString(" ", withString: "-"))-\(actualPage + 1)" 710 | // let url = NSURL(string:tempurl)! 711 | // YouJizzCharge(url) 712 | // } 713 | 714 | // let url = NSURL(string: "http://www.xvideos.com/?k=\(textToSearch.stringByReplacingOccurrencesOfString(" ", withString: "+"))&p=\(actualPage)") 715 | // let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in 716 | // let stringa = NSString(data: data!, encoding: NSUTF8StringEncoding)! 717 | // var imageLink = Utils.GetStringsByRegularExpression(stringa, regularexp: "]*?\\s+)?src=\"http://img\\-([^\"]*)\"") 718 | // var titleAndHref = Utils.GetStringsByRegularExpression(stringa, regularexp: "]*?\\s+)?href=\"/video([^\"]*)\"?\\stitle=\"([^\"]*)\"") 719 | // if(imageLink.count == titleAndHref.count) 720 | // { 721 | // for i in 0 ..< titleAndHref.count 722 | // { 723 | // let imglinkTemp = imageLink[i].stringByReplacingOccurrencesOfString(" 1){ 745 | // self.previousButton(i) 746 | // i += 1 747 | // } 748 | // self.homeButton(i) 749 | // i += 1 750 | // self.scroll.contentSize = CGSize(width: self.bounds.width, height: CGFloat(self.calculatePosition(i).maxY + 180)) 751 | // self.scroll.scrollEnabled = true 752 | // } 753 | // } 754 | // task.resume() 755 | } 756 | 757 | func SortBySearch(_ howSort: String,textToSearch: String){ 758 | videos = [Video]() 759 | self.isSearch = true 760 | let subViews = self.scroll.subviews 761 | for subview in subViews{ 762 | subview.removeFromSuperview() 763 | } 764 | } 765 | 766 | func TextField(_ index: Int) 767 | { 768 | field.frame = calculatePositionLarger(index) 769 | field.backgroundColor = UIColor.white 770 | scroll.addSubview(field) 771 | 772 | } 773 | 774 | func searchButton(_ index: Int){ 775 | let button = UIButton(type: UIButton.ButtonType.system) 776 | button.backgroundColor = UIColor.black 777 | button.frame = calculatePosition(index) 778 | button.setTitle("Search", for: UIControl.State()) 779 | // button.tag = index + 1) 780 | button.addTarget(self, action: #selector(HomeSelectionController.search(_:)), for: .primaryActionTriggered) 781 | button.clipsToBounds = true 782 | scroll.addSubview(button) 783 | } 784 | 785 | 786 | func homeButton(_ index: Int){ 787 | let button = UIButton(type: UIButton.ButtonType.system) 788 | button.backgroundColor = UIColor.black 789 | button.frame = calculatePosition(index) 790 | button.setTitle("Home", for: UIControl.State()) 791 | // button.tag = index + 1) 792 | button.addTarget(self, action: #selector(HomeSelectionController.home(_:)), for: .primaryActionTriggered) 793 | button.clipsToBounds = true 794 | scroll.addSubview(button) 795 | } 796 | func nextButton(_ index: Int){ 797 | let button = UIButton(type: UIButton.ButtonType.system) 798 | button.backgroundColor = UIColor.black 799 | button.frame = calculatePosition(index) 800 | button.setTitle("Next Page", for: UIControl.State()) 801 | button.tag = index 802 | button.addTarget(self, action: #selector(HomeSelectionController.next(_:)), for: .primaryActionTriggered) 803 | button.clipsToBounds = true 804 | scroll.addSubview(button) 805 | 806 | // scroll.contentSize = CGSize(width: bounds.width, height: CGFloat(y + 180)) 807 | // scroll.scrollEnabled = true 808 | } 809 | 810 | func sortButton(_ index: Int,text: Selector){ 811 | let button = UIButton(type: UIButton.ButtonType.system) 812 | let title = text.description.replacingOccurrences(of: ":", with: "") 813 | if(selectedSort == title) 814 | { 815 | button.backgroundColor = UIColor.gray 816 | }else{ 817 | button.backgroundColor = UIColor.black 818 | } 819 | button.frame = calculatePosition(index) 820 | button.setTitle(title,for: UIControl.State()) 821 | // button.tag = index + 1) 822 | button.addTarget(self, action: text, for: .primaryActionTriggered) 823 | 824 | button.clipsToBounds = true 825 | scroll.addSubview(button) 826 | } 827 | 828 | 829 | 830 | func previousButton(_ index: Int){ 831 | let button = UIButton(type: UIButton.ButtonType.system) 832 | button.frame = calculatePosition(index) 833 | button.setTitle("Previous Page", for: UIControl.State()) 834 | button.tag = index 835 | button.addTarget(self, action: #selector(HomeSelectionController.previous(_:)), for: .primaryActionTriggered) 836 | button.clipsToBounds = true 837 | scroll.addSubview(button) 838 | // scroll.clipsToBounds = true 839 | } 840 | 841 | @objc func tapped(_ sender: UIButton) { 842 | let object = self.videos[sender.tag] 843 | self.performSegue(withIdentifier: "Video", sender: object) 844 | } 845 | 846 | 847 | @objc func next(_ sender: UIButton) { 848 | actualPage += 1 849 | //TODO ADD SORT PAGINATION 850 | if(!isSearch){ 851 | if(!isSorted) 852 | { 853 | self.showPage(actualPage) 854 | }else 855 | { 856 | // self.SortByHome(selectedSort) 857 | } 858 | } 859 | else{ 860 | if(!isSorted){ 861 | self.searchText(field.text!) 862 | }else{ 863 | self.SortBySearch(selectedSort, textToSearch: field.text!) 864 | } 865 | } 866 | } 867 | 868 | 869 | @objc func previous(_ sender: UIButton) { 870 | actualPage -= 1 871 | if(!isSearch){ 872 | if(!isSorted) 873 | { 874 | if(actualPage < 0) 875 | { 876 | actualPage = 0 877 | } 878 | self.showPage(actualPage) 879 | }else 880 | { 881 | // self.SortByHome(selectedSort) 882 | } 883 | } 884 | else{ 885 | if(!isSorted){ 886 | self.searchText(field.text!) 887 | }else{ 888 | self.SortBySearch(selectedSort, textToSearch: field.text!) 889 | } 890 | } 891 | } 892 | 893 | @objc func home(_ sender: UIButton){ 894 | self.actualPage = 0 895 | self.showPage(actualPage) 896 | } 897 | 898 | 899 | @objc func search(_ sender: UIButton){ 900 | self.actualPage = 0 901 | self.searchText(field.text!) 902 | } 903 | 904 | 905 | override func prepare(for segue: UIStoryboardSegue, sender: Any!) { 906 | let video = sender as! Video 907 | if segue.identifier == "Video"{ 908 | let vc = segue.destination as! VideoController 909 | vc.video = video 910 | vc.webSiteTitle = selectedSite 911 | } 912 | } 913 | 914 | 915 | override func didReceiveMemoryWarning() { 916 | super.didReceiveMemoryWarning() 917 | // Dispose of any resources that can be recreated. 918 | } 919 | 920 | func calculatePosition(_ index: Int) -> CGRect 921 | { 922 | let numImagePerRow = Int(bounds.width) / (Int(300) + 30) 923 | let width = CGFloat(300) 924 | let height = CGFloat(169) 925 | let x = ((index) % numImagePerRow) * Int(width) + 20 * ((index) % numImagePerRow + 1) 926 | let y = (index) / numImagePerRow * Int(height) + 20 * ((index) / numImagePerRow + 1) 927 | return CGRect(x: CGFloat(x), y: CGFloat(y), width: width, height: height) 928 | } 929 | 930 | func calculatePositionLarger(_ index: Int) -> CGRect 931 | { 932 | let numImagePerRow = Int(bounds.width) / (Int(600) + 30) 933 | let width = CGFloat(600) 934 | let height = CGFloat(169) 935 | let x = ((index) % numImagePerRow) * Int(width) + 20 * ((index) % numImagePerRow + 1) 936 | let y = (index) / numImagePerRow * Int(height) + 20 * ((index) / numImagePerRow + 1) 937 | return CGRect(x: CGFloat(x), y: CGFloat(y), width: width, height: height) 938 | } 939 | 940 | func calculatePosition(_ index: Int, image: UIImage) -> CGRect 941 | { 942 | let numImagePerRow = Int(bounds.width) / (Int(300) + 30) 943 | let width = CGFloat(300) 944 | let height = CGFloat(169) 945 | let x = (index % numImagePerRow) * Int(width) + 20 * (index % numImagePerRow + 1) 946 | let y = index / numImagePerRow * Int(height) + 20 * (index / numImagePerRow + 1) 947 | return CGRect(x: CGFloat(x), y: CGFloat(y), width: width, height: height) 948 | } 949 | 950 | 951 | func calculatePositionSite(_ index: Int, image: UIImage) -> CGRect 952 | { 953 | let numImagePerRow = Int(bounds.width) / (Int(300) + 30) 954 | let width = CGFloat(300) 955 | let height = CGFloat(120) 956 | let x = (index % numImagePerRow) * Int(width) + 20 * (index % numImagePerRow + 1) 957 | let y = index / numImagePerRow * Int(height) + 20 * (index / numImagePerRow + 1) 958 | return CGRect(x: CGFloat(x), y: CGFloat(y), width: width, height: height) 959 | } 960 | 961 | 962 | func createButton(_ image: UIImage, index: Int,video: Video){ 963 | let button = UIButton(type: UIButton.ButtonType.system) 964 | button.contentVerticalAlignment = UIControl.ContentVerticalAlignment.bottom 965 | button.titleLabel?.lineBreakMode = .byTruncatingTail 966 | button.titleLabel?.backgroundColor = UIColor(red: 238.0/255.0, green: 238.0/255.0, blue: 238.0/255.0, alpha: 1.0) 967 | button.setTitleColor(UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0), for: UIControl.State()) 968 | button.titleLabel?.font = UIFont(name: "Arial", size: 25) 969 | button.setTitle(String(htmlEncodedString: video.Title), for: UIControl.State()) 970 | button.imageView?.contentMode = UIView.ContentMode.scaleAspectFit 971 | button.frame = calculatePosition(index, image: image) 972 | button.setBackgroundImage(image, for: UIControl.State()) 973 | button.tag = index - 5 974 | button.addTarget(self, action: #selector(HomeSelectionController.tapped(_:)), for: .primaryActionTriggered) 975 | button.clipsToBounds = true 976 | scroll.addSubview(button) 977 | scroll.clipsToBounds = true 978 | } 979 | 980 | func chargeImageAsync(_ image: String, index: Int, video: Video){ 981 | let url = URL(string: image) 982 | if((url == nil || (url?.hashValue) == nil)){ 983 | let image = UIImage(named: "ImageNotfound.png") 984 | DispatchQueue.main.async{ 985 | self.createButton(image!,index: index,video: video) 986 | } 987 | }else{ 988 | let task = URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in 989 | if(data != nil){ 990 | let image = UIImage(data: data!) 991 | if(image != nil){ 992 | DispatchQueue.main.async{ 993 | self.createButton(image!,index: index,video: video) 994 | } 995 | } 996 | } 997 | }) 998 | task.resume() 999 | } 1000 | } 1001 | 1002 | 1003 | 1004 | } 1005 | -------------------------------------------------------------------------------- /XvideosViewer/ImageNotfound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimiko88/Tvos-PornSitesViewer/8748cb1477429704cdb2d6bfc8ea93540c8b82cc/XvideosViewer/ImageNotfound.png -------------------------------------------------------------------------------- /XvideosViewer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | CFBundleDevelopmentRegion 11 | en 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | $(PRODUCT_NAME) 20 | CFBundlePackageType 21 | APPL 22 | CFBundleShortVersionString 23 | 1.0 24 | CFBundleSignature 25 | ???? 26 | CFBundleVersion 27 | 1 28 | LSRequiresIPhoneOS 29 | 30 | UIMainStoryboardFile 31 | Main 32 | UIRequiredDeviceCapabilities 33 | 34 | arm64 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /XvideosViewer/SeeVideo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SeeVideo.swift 3 | // XvideosViewer 4 | // 5 | // Created by kimiko88 on 21/03/16. 6 | // Copyright © 2016 kimiko88. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import AVKit 12 | 13 | class AVVideoPlayerController: AVPlayerViewController{ 14 | var downloadVideo: DownloadLink! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | let url = URL(string: String(htmlEncodedString: downloadVideo.Link)) 20 | player = AVPlayer(url: url!) 21 | player?.play() 22 | Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(AVVideoPlayerController.tick), userInfo: nil, repeats: true) 23 | 24 | } 25 | 26 | 27 | 28 | @objc func tick() {//Failed case 29 | if(player!.status == .failed) 30 | { 31 | let url = URL(string: String(htmlEncodedString: downloadVideo.Link)) 32 | let item = AVPlayerItem(url: url!) 33 | player?.replaceCurrentItem(with: item) 34 | } 35 | } 36 | } 37 | 38 | 39 | extension String { 40 | init(htmlEncodedString: String) { 41 | let encodedData = htmlEncodedString.data(using: String.Encoding.utf8)! 42 | let options = [NSAttributedString.DocumentReadingOptionKey.documentType: 43 | NSAttributedString.DocumentType.html] 44 | var attributedString = NSAttributedString() 45 | do{ 46 | attributedString = try NSAttributedString(data: encodedData, options: options, documentAttributes: nil) 47 | 48 | }catch{ 49 | print("error") 50 | } 51 | self.init(stringLiteral: attributedString.string) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /XvideosViewer/Utils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.swift 3 | // XvideosViewer 4 | // 5 | // Created by kimiko88 on 22/03/16. 6 | // Copyright © 2016 kimiko88. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | class Utils{ 13 | 14 | static func GetStringsByRegularExpression(_ stringWhereFind: NSString,regularexp : String) -> [String] 15 | { 16 | var results = [String]() 17 | do { 18 | let regex = try NSRegularExpression(pattern: regularexp, options: NSRegularExpression.Options.caseInsensitive) 19 | let range = NSMakeRange(0, stringWhereFind.length) 20 | let matches = regex.matches(in: stringWhereFind as String, options: NSRegularExpression.MatchingOptions.withoutAnchoringBounds, range: range) 21 | for match in matches{ 22 | results.append(stringWhereFind.substring(with: match.range)) 23 | } 24 | }catch{ 25 | print("error"); 26 | } 27 | return results 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /XvideosViewer/VideoController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoController.swift 3 | // XvideosViewer 4 | // 5 | // Created by fabrizio chimienti on 21/03/16. 6 | // Copyright © 2016 kimiko88. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | class DownloadLink{ 13 | var Link: String 14 | var Title: String 15 | init(link: String, title: String){ 16 | Link = link 17 | Title = title 18 | } 19 | } 20 | 21 | class VideoController: UIViewController { 22 | 23 | var bounds = UIScreen.main.bounds 24 | var video: Video! 25 | var webSiteTitle: String = "" 26 | 27 | 28 | var downloadLinks = [DownloadLink]() 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | 33 | if(webSiteTitle == "YouPorn") 34 | { 35 | YouPornVideo() 36 | } 37 | if(webSiteTitle == "Xvideos") 38 | { 39 | XvideosVideo() 40 | } 41 | if(webSiteTitle == "Pornhub") 42 | { 43 | PornhubVideo() 44 | } 45 | if(webSiteTitle == "RedTube") 46 | { 47 | RedTubeVideo() 48 | } 49 | if(webSiteTitle == "Tube8") 50 | { 51 | Tube8Video() 52 | } 53 | if(webSiteTitle == "Thumbzilla") 54 | { 55 | ThumbzillaVideo() 56 | } 57 | if(webSiteTitle == "XTube") 58 | { 59 | XTubeVideo() 60 | } 61 | //USE Only flv but tvos can't read that format 62 | // if(webSiteTitle == "YouJizz") 63 | // { 64 | // YouJizzVideo() 65 | // } 66 | // let url = NSURL(string: self.video.Link) 67 | // let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in 68 | // let stringa = NSString(data: data!, encoding: NSUTF8StringEncoding)! 69 | // do { 70 | // let regex = try NSRegularExpression(pattern: "http://(\\w[^\"|^\']+/videos/\\w[^\"|^\']+)", options: NSRegularExpressionOptions.CaseInsensitive) 71 | // let range = NSMakeRange(0, stringa.length) 72 | // let matches = regex.matchesInString(stringa as String, options: NSMatchingOptions.WithoutAnchoringBounds, range: range) 73 | // for match in matches{ 74 | // let result = stringa.substringWithRange(match.range) 75 | // if(result.rangeOfString("mp4") != nil){ 76 | // var title = "mp4 quality" 77 | // if(result.rangeOfString("3gp") != nil) 78 | // { 79 | // title = "3gp quality" 80 | // } 81 | // print(result) 82 | // self.downloadLinks.append(DownloadLink(link: result, title: title)) 83 | // } 84 | // } 85 | // }catch{ 86 | // print("error"); 87 | // } 88 | // dispatch_async(dispatch_get_main_queue()){ 89 | // var i = 0 90 | // 91 | // for downloadLink in self.downloadLinks{ 92 | // if(downloadLink.Title.rangeOfString("3GP") == nil)//AVPlayer for tvos can't play 3GP file 93 | // { 94 | // self.createButton(downloadLink,index: i) 95 | // } 96 | // i += 1; 97 | // } 98 | // } 99 | // } 100 | // task.resume() 101 | } 102 | 103 | func YouPornVideo(){ 104 | let url = URL(string: self.video.Link) 105 | let task = URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in 106 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 107 | let strin = String(stringa) 108 | let splitted = strin.split{$0 == " "}.map(String.init) 109 | for var i in 0 ..< splitted.count 110 | { 111 | let oo = splitted[i] 112 | 113 | if (oo.range(of: "downloadOption") != nil){ 114 | var tempLink = "" 115 | var tempTitle = "" 116 | var start = false 117 | i += 1 118 | while((splitted[i].range(of: "/a>")) == nil) 119 | { 120 | i += 1 121 | if(splitted[i].range(of: "href=") != nil){ 122 | tempLink = splitted[i] 123 | } 124 | 125 | if(splitted[i].range(of: "\'>") != nil && tempLink.count > 2){ 126 | start = true 127 | } 128 | if(start) 129 | { 130 | tempTitle += " " + splitted[i] 131 | } 132 | 133 | } 134 | let link = tempLink.replacingOccurrences(of: "href='", with: "") 135 | let title = tempTitle.replacingOccurrences(of: " Video'>", with: "").replacingOccurrences(of: "\n 2) 271 | { 272 | let title = titlelink[0].replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "{", with: "") 273 | print(title) 274 | let link = titlelink[2].replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "\\", with: "").replacingOccurrences(of: "}", with: "") 275 | self.downloadLinks.append(DownloadLink(link: link, title: title)) 276 | } 277 | } 278 | } 279 | // } 280 | }catch{ 281 | print("error"); 282 | } 283 | DispatchQueue.main.async{ 284 | var i = 0 285 | 286 | for downloadLink in self.downloadLinks{ 287 | // if(downloadLink.Title.rangeOfString("3GP") == nil)//AVPlayer for tvos can't play 3GP file 288 | // { 289 | self.createButton(downloadLink,index: i) 290 | // } 291 | i += 1; 292 | } 293 | } 294 | }) 295 | task.resume() 296 | } 297 | 298 | 299 | func Tube8Video(){ 300 | 301 | let url = URL(string: self.video.Link) 302 | let task = URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in 303 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 304 | do { 305 | let regex = try NSRegularExpression(pattern: "quality_\\w\\w\\w\\w\":\"[^\"]*\"", options: NSRegularExpression.Options.caseInsensitive) 306 | let range = NSMakeRange(0, stringa.length) 307 | let matches = regex.matches(in: stringa as String, options: NSRegularExpression.MatchingOptions.withoutAnchoringBounds, range: range) 308 | for match in matches{ 309 | let result = stringa.substring(with: match.range) 310 | let splitted = result.split{$0 == "\""}.map(String.init) 311 | print(splitted) 312 | if(splitted.count > 2 && splitted[2].count > 10) 313 | { 314 | let title = splitted[0].replacingOccurrences(of: "\"", with: "") 315 | print(title) 316 | let link = splitted[2].replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "\\", with: "") 317 | self.downloadLinks.append(DownloadLink(link: link, title: title)) 318 | } 319 | } 320 | // } 321 | }catch{ 322 | print("error"); 323 | } 324 | DispatchQueue.main.async{ 325 | var i = 0 326 | 327 | for downloadLink in self.downloadLinks{ 328 | // if(downloadLink.Title.rangeOfString("3GP") == nil)//AVPlayer for tvos can't play 3GP file 329 | // { 330 | self.createButton(downloadLink,index: i) 331 | // } 332 | i += 1; 333 | } 334 | } 335 | }) 336 | task.resume() 337 | } 338 | 339 | 340 | func ThumbzillaVideo(){ 341 | let url = URL(string: self.video.Link) 342 | let task = URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in 343 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 344 | do { 345 | let regex = try NSRegularExpression(pattern: "data-quality=\"[^\"]*\">(\\w+)<", options: NSRegularExpression.Options.caseInsensitive) 346 | let range = NSMakeRange(0, stringa.length) 347 | let matches = regex.matches(in: stringa as String, options: NSRegularExpression.MatchingOptions.withoutAnchoringBounds, range: range) 348 | for match in matches{ 349 | let result = stringa.substring(with: match.range) 350 | let link = Utils.GetStringsByRegularExpression(result as NSString, regularexp: "\"[^\"]*\"")[0].replacingOccurrences(of: "\"", with: "") 351 | let title = Utils.GetStringsByRegularExpression(result as NSString, regularexp: ">(\\w*)<")[0].replacingOccurrences(of: ">", with: "").replacingOccurrences(of: "<", with: "") 352 | print(link) 353 | if( link.count > 10) 354 | { 355 | self.downloadLinks.append(DownloadLink(link: link, title: title)) 356 | } 357 | } 358 | // } 359 | }catch{ 360 | print("error"); 361 | } 362 | DispatchQueue.main.async{ 363 | var i = 0 364 | 365 | for downloadLink in self.downloadLinks{ 366 | // if(downloadLink.Title.rangeOfString("3GP") == nil)//AVPlayer for tvos can't play 3GP file 367 | // { 368 | self.createButton(downloadLink,index: i) 369 | // } 370 | i += 1; 371 | } 372 | } 373 | }) 374 | task.resume() 375 | } 376 | 377 | func XTubeVideo(){ 378 | let url = URL(string: self.video.Link) 379 | let task = URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in 380 | let stringa = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! 381 | do { 382 | let regex = try NSRegularExpression(pattern: "quality_\\w\\w\\w\\w\":\"(.*?)\"", options: NSRegularExpression.Options.caseInsensitive) 383 | let range = NSMakeRange(0, stringa.length) 384 | let matches = regex.matches(in: stringa as String, options: NSRegularExpression.MatchingOptions.withoutAnchoringBounds, range: range) 385 | for match in matches{ 386 | let result = stringa.substring(with: match.range) 387 | let splitted = result.split{$0 == "\""}.map(String.init) 388 | if(splitted.count > 2) 389 | { 390 | let title = splitted[0] 391 | let link = splitted[2].removingPercentEncoding! 392 | self.downloadLinks.append(DownloadLink(link: link, title: title)) 393 | } 394 | } 395 | // } 396 | }catch{ 397 | print("error"); 398 | } 399 | DispatchQueue.main.async{ 400 | var i = 0 401 | 402 | for downloadLink in self.downloadLinks{ 403 | // if(downloadLink.Title.rangeOfString("3GP") == nil)//AVPlayer for tvos can't play 3GP file 404 | // { 405 | self.createButton(downloadLink,index: i) 406 | // } 407 | i += 1; 408 | } 409 | } 410 | }) 411 | task.resume() 412 | } 413 | 414 | //When tvos could read flv file 415 | // func YouJizzVideo(){ 416 | // let url = NSURL(string: self.video.Link) 417 | // let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in 418 | // let stringa = NSString(data: data!, encoding: NSUTF8StringEncoding)! 419 | // do { 420 | // let regex = try NSRegularExpression(pattern: "a(.*?)>Download", options: NSRegularExpressionOptions.CaseInsensitive) 421 | // let range = NSMakeRange(0, stringa.length) 422 | // let matches = regex.matchesInString(stringa as String, options: NSMatchingOptions.WithoutAnchoringBounds, range: range) 423 | // for match in matches{ 424 | // let result = stringa.substringWithRange(match.range) 425 | // 426 | // let link = Utils.GetStringsByRegularExpression(result, regularexp: "href=[\"|'][^\"|^']*[\"|']")[0].stringByReplacingOccurrencesOfString("href=\"", withString: "").stringByReplacingOccurrencesOfString("\"", withString: "")//.stringByRemovingPercentEncoding! 427 | // print(link) 428 | // self.downloadLinks.append(DownloadLink(link: link+"&start=0", title: "flv")) 429 | // } 430 | // // } 431 | // }catch{ 432 | // print("error"); 433 | // } 434 | // dispatch_async(dispatch_get_main_queue()){ 435 | // var i = 0 436 | // 437 | // for downloadLink in self.downloadLinks{ 438 | // // if(downloadLink.Title.rangeOfString("3GP") == nil)//AVPlayer for tvos can't play 3GP file 439 | // // { 440 | // self.createButton(downloadLink,index: i) 441 | // // } 442 | // i += 1; 443 | // } 444 | // } 445 | // } 446 | // task.resume() 447 | // } 448 | 449 | @objc func tapped(_ sender: UIButton) { 450 | let object = self.downloadLinks[sender.tag] 451 | self.performSegue(withIdentifier: "SeeVideo", sender: object) 452 | } 453 | 454 | 455 | 456 | 457 | override func prepare(for segue: UIStoryboardSegue, sender: Any!) { 458 | let video = sender as! DownloadLink 459 | if segue.identifier == "SeeVideo"{ 460 | let vc = segue.destination as! AVVideoPlayerController 461 | vc.downloadVideo = video 462 | } 463 | } 464 | 465 | func createButton(_ download: DownloadLink, index: Int){ 466 | let numImagePerRow = Int(bounds.width) / (Int(1600) + 20) 467 | let width = CGFloat(1600) 468 | let height = CGFloat(180) 469 | let x = (index % numImagePerRow) * Int(width) + 20 * (index % numImagePerRow) 470 | let y = index / numImagePerRow * Int(height) + 20 * (index / numImagePerRow) 471 | let button = UIButton(type: UIButton.ButtonType.system) 472 | button.frame = CGRect(x: CGFloat(x), y: CGFloat(y), width: width, height: height) 473 | button.setTitle(download.Title, for: UIControl.State()) 474 | button.tag = index 475 | button.addTarget(self, action: #selector(VideoController.tapped(_:)), for: .primaryActionTriggered) 476 | button.clipsToBounds = true 477 | self.view.addSubview(button) 478 | self.view.clipsToBounds = true 479 | } 480 | 481 | 482 | 483 | 484 | override func didReceiveMemoryWarning() { 485 | super.didReceiveMemoryWarning() 486 | } 487 | 488 | } 489 | 490 | 491 | // WHEN TVOS WILL READ .flv 492 | // let tempurl = NSURL(string: self.video.Link) 493 | // let muturl = NSMutableURLRequest(URL: tempurl!) 494 | // 495 | // muturl.setValue("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36", forHTTPHeaderField: "User-Agent") 496 | // let url = muturl as NSURLRequest 497 | // 498 | // let task = NSURLSession.sharedSession().dataTaskWithRequest(url) {(data, response, error) in 499 | // let stringa = NSString(data: data!, encoding: NSUTF8StringEncoding)! 500 | // // print(stringa) 501 | // do {// CGRect 103 | { 104 | // let numImagePerRow = Int(bounds.width) / (Int(image.size.width) + 20) 105 | let numImagePerRow = Int(bounds.width) / (Int(300) + 25) 106 | // let width = image.size.width 107 | // let height = image.size.height 108 | let width = CGFloat(300) 109 | let height = CGFloat(120) 110 | let x = (index % numImagePerRow) * Int(width) + 20 * (index % numImagePerRow + 1) 111 | let y = index / numImagePerRow * Int(height) + 20 * (index / numImagePerRow + 1) 112 | return CGRect(x: CGFloat(x), y: CGFloat(y), width: width, height: height) 113 | } 114 | 115 | 116 | func chargeSiteImageAsync(_ image: String, index: Int, name: String){ 117 | let url = URL(string: image) 118 | if(( (url == nil || (url?.hashValue) == nil) || name == "PornMD")){ 119 | var image = UIImage(named: "ImageNotfound.png") 120 | if(name == "PornMD") 121 | { 122 | image = UIImage(named: "PornMD.png")! 123 | } 124 | DispatchQueue.main.async{ 125 | self.createSiteButton(image!,index: index,name: name) 126 | } 127 | }else{ 128 | let task = URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in 129 | var image = UIImage(named: "ImageNotfound.png") 130 | if(data != nil){ 131 | image = UIImage(data: data!) 132 | } 133 | DispatchQueue.main.async{ 134 | self.createSiteButton(image!,index: index,name: name) 135 | } 136 | }) 137 | task.resume() 138 | } 139 | } 140 | 141 | 142 | func createSiteButton(_ image: UIImage, index: Int,name: String){ 143 | let button = UIButton(type: UIButton.ButtonType.system) 144 | button.contentVerticalAlignment = UIControl.ContentVerticalAlignment.bottom 145 | button.titleLabel?.lineBreakMode = .byTruncatingTail 146 | button.titleLabel?.backgroundColor = UIColor(red: 238.0/255.0, green: 238.0/255.0, blue: 238.0/255.0, alpha: 1.0) 147 | button.setTitleColor(UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0), for: UIControl.State()) 148 | button.titleLabel?.font = UIFont(name: "Arial", size: 25) 149 | button.setTitle(name, for: UIControl.State()) 150 | button.imageView?.contentMode = UIView.ContentMode.scaleAspectFit 151 | button.frame = calculatePositionSite(index, image: image) 152 | button.setBackgroundImage(image, for: UIControl.State()) 153 | button.tag = index 154 | button.addTarget(self, action: #selector(ViewController.tappedSite(_:)), for: .primaryActionTriggered) 155 | button.clipsToBounds = true 156 | scroll.addSubview(button) 157 | scroll.clipsToBounds = true 158 | } 159 | 160 | 161 | } 162 | 163 | -------------------------------------------------------------------------------- /XvideosViewer/XvideosViewer.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | XvideosViewer.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /XvideosViewer/XvideosViewer.xcdatamodeld/XvideosViewer.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --------------------------------------------------------------------------------