commit 04efcce3c1b8c22af3421914f8082252724945cb Author: Paul Wilde Date: Wed Oct 16 13:47:32 2024 +0100 first diff --git a/Pimvidious b/Pimvidious new file mode 100755 index 0000000..4cdd32e Binary files /dev/null and b/Pimvidious differ diff --git a/Pimvidious.nimble b/Pimvidious.nimble new file mode 100644 index 0000000..6542aa2 --- /dev/null +++ b/Pimvidious.nimble @@ -0,0 +1,14 @@ +# Package + +version = "0.1.0" +author = "Paul Wilde" +description = "Porninvidious re-made in Nim" +license = "BSD-3-Clause" +srcDir = "src" +bin = @["Pimvidious"] + + +# Dependencies + +requires "nim >= 2.0.0" +requires "mummy" diff --git a/nim.cfg b/nim.cfg new file mode 100644 index 0000000..521e21d --- /dev/null +++ b/nim.cfg @@ -0,0 +1 @@ +-d:ssl diff --git a/src/Pimvidious.nim b/src/Pimvidious.nim new file mode 100644 index 0000000..c0e4263 --- /dev/null +++ b/src/Pimvidious.nim @@ -0,0 +1,54 @@ +import mummy, mummy/routers +import tables, strutils, mimetypes + +import genpage + +let ip = "0.0.0.0" +let port = 8069 + +var mimes = newMimeTypes() + +proc pageHandler(request: Request) = + echo request.uri + var headers: HttpHeaders + let content = genpage(path=request.uri) + headers["content-type"] = "text/html" + request.respond(200,headers, content) + +proc videoHandler(request: Request) = + echo request.uri + var headers: HttpHeaders + let content = genpage(path=request.uri, video_uri=request.uri) + headers["content-type"] = "text/html" + request.respond(200, headers, content) + +proc staticFileHandler(request: Request) = + var file = request.uri[1..^1] + if file == "favicon.ico": file = "favicon.png" + {.gcsafe.}: + if RESOURCES.hasKey(file): + var headers: HttpHeaders + let ext = file.split(".")[^1] + let content_type = mimes.getMimetype(ext) + headers["content-type"] = content_type + request.respond(200, headers, RESOURCES[file]) + else: + request.respond(404) + + +proc createRouter(): Router = + var router: Router + router.get("/", pageHandler) + router.get("/video.*/*", videoHandler) + router.get("/video.*/*/*/*", videoHandler) + router.get("/favicon.ico", staticFileHandler) + router.get("/favicon.png", staticFileHandler) + router.get("/css.css", staticFileHandler) + return router + + +when isMainModule: + let server = newServer(createRouter()) + echo "Connected to ", ip, ":", port + server.serve(Port(port),address=ip) + diff --git a/src/genpage.nim b/src/genpage.nim new file mode 100644 index 0000000..6daff0a --- /dev/null +++ b/src/genpage.nim @@ -0,0 +1,128 @@ +import httpclient +import os, strutils, strformat, tables, re, sugar, uri + +type + Urls = seq[string] + Thumbs = seq[string] + +proc cacheResources(): Table[string, string] = + echo "Compiling Resources..." + var res: Table[string,string] + for file in walkDir("src/resources"): + let path = file.path.split("/")[^1] + res[path] = staticRead(file.path.replace("src/","")) + echo "Done" + return res + +const RESOURCES*: Table[string, string] = cacheResources() + +proc request(uri: string): string = + var client = newHttpClient() + try: + echo "Requesting ", uri + let content = client.getContent(uri) + return content + except: + return "Not Found" + finally: + client.close() + +proc parseUrls(content: string): seq[string] = + let url_re = re"""
""" + let urls = collect: + for url in content.findAll(url_re): + url.split("\"")[3] + return urls + +proc parseThumbs(content: string): seq[string] = + let thumb_re = re"""data-src="(.*)"""" + let thumbs = collect: + for thumb in content.findAll(thumb_re): + thumb.split("\"")[1] + return thumbs + +proc setUpVideo(content: string, video_uri: string): (string, Urls, Thumbs) = + let rel_vids_re = re"""video_related=(.+)""" + let vid_url_re = re"""setVideoUrl(High|Low)(.*)""" + let vid_hls_re = re"""setVideoHLS(.*)""" + let vid_thumb_re = re"""setThumbUrl(.*)""" + let related_vids = collect: + for vid in content.findAll(rel_vids_re): + vid.replace(",","\n") + let videos = content.findAll(vid_url_re) + var video = videos[0].split("'")[1] + let video_low = videos[1].split("'")[1] + var video_hls: string + var video_hls_matches = content.findAll(vid_hls_re) + if video_hls_matches.len > 0: + video_hls = video_hls_matches[0].split("'")[1] + if video == "": + video = video_low + let video_thumb = content.findAll(vid_thumb_re)[0].split("'")[1] + var HTML_VIDEO = fmt"""
""" + if video_hls != "": + HTML_VIDEO &= fmt"""

HD Stream:


(use with a video player)""" + HTML_VIDEO &= "
" + var thumbs: Thumbs = @[] + var urls: Urls = @[] + for vid in related_vids: + thumbs = collect: + for thumb in vid.findAll(re""""i":(.*)"""): + thumb.replace("\\","").replace("\"i\":","").replace("\"","") + urls = collect: + for url in vid.findAll(re""""u":(.*)"""): + url.replace("\\","").replace("\"u\":","").replace("\"","") + return (HTML_VIDEO, urls, thumbs) + +proc getPagination(content:string): string = + let page_re = re"""""" + let pagination = content.findAll(page_re) + if pagination.len > 0: + return pagination[0] + +proc compilePage(content: string, video_uri: string = "", search_query: string = ""): string = + var + page: string = "" + urls: Urls + thumbs: Thumbs + pagination: string = getPagination(content) + page &= RESOURCES["html_start"].replace("**QUERY**",search_query) + if video_uri != "": + var video: string + (video, urls, thumbs) = setUpVideo(content, video_uri) + page &= fmt"
{video}
" + else: + urls = parseUrls(content) + thumbs = parseThumbs(content) + if pagination != "": + page &= pagination + page &= "
" + for idx, url in urls: + let title = url.split("/")[^1].replace("_"," ") + if title == "THUMBNUM": + # This was in Porninvidious, but that uses cut instead of last index, + # so probably not necessary here. Leaving a note in case + echo "THUMBNUM - do something else here" + page &= fmt"""

{title}
""" + page &= "
" + if pagination != "": + page &= pagination + page &= "" + page &= RESOURCES["html_end"] + return page + +const XV = "https://www.xvideos.com" +proc genpage*(path: string, video_uri: string = ""): string = + let content = request(XV & path) + var search_query: string + if video_uri == "": + let search = parseUri(path) + for item in search.query.split("&"): + let parm = item.split("=") + if parm[0] == "k": + search_query = parm[1] + return compilePage(content, search_query = search_query) + else: + return compilePage(content, video_uri) diff --git a/src/resources/css.css b/src/resources/css.css new file mode 100644 index 0000000..752a254 --- /dev/null +++ b/src/resources/css.css @@ -0,0 +1,90 @@ +h1 { + color: white; + margin-top: 4vh; + margin-left: 4%; +} +h3 { + color: white; + display: inline; +} +#infoblock { + margin-bottom: 8vh; + color: white; +} +a { + color: white; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +body { + margin: 0; + padding: 0; + background: #111; +} +form { + text-align: center; + margin-bottom: 10vh; +} + +section { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 10px; +} + +div { + left: 0; + right: 0; + padding: 1em; + text-align: center; +} + +img { + width: 80%; +} + +video { + margin-top: -4vh; + max-width:100%; + min-width:80%; + margin-bottom: 0.5vh; +} +.pagination ul li { + display:inline-block; + margin-right:20px; +} +.pagination ul li.no-page { + display:none; +} +.pagination ul li a.active { + color:grey; +} + +@media screen and (max-width: 1200px) { /* Half screen */ + section { + grid-template-columns: repeat(2, 1fr); + } + div { + font-size: 1.2rem; + } +} + +@media screen and (max-width: 1000px) { /* Mobile */ + section { + grid-template-columns: repeat(1, 1fr); + } + + h1, #infoblock, div { + font-size: 2em; + } + + form input { + font-size: 2rem; + } + video { + min-width:100%;} +} diff --git a/src/resources/favicon.png b/src/resources/favicon.png new file mode 100644 index 0000000..5dfbe4f Binary files /dev/null and b/src/resources/favicon.png differ diff --git a/src/resources/html_end b/src/resources/html_end new file mode 100644 index 0000000..73e46b9 --- /dev/null +++ b/src/resources/html_end @@ -0,0 +1,2 @@ + + diff --git a/src/resources/html_start b/src/resources/html_start new file mode 100644 index 0000000..bfeb29f --- /dev/null +++ b/src/resources/html_start @@ -0,0 +1,12 @@ + + + + + Pimvidious + + +

Pimvidious

+
+ + +