Skip to content

Commit

Permalink
feat: simple rick-rolling implementation
Browse files Browse the repository at this point in the history
A Flask server that takes a URL in parameter, and serves the same
page, but with all the links pointing to YouTube's rick-rolling video.
  • Loading branch information
derlin committed Apr 1, 2022
0 parents commit e15f2a1
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.pyc
__pycache__
venv
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM python:3.9-alpine3.15

COPY requirements.txt /app/
RUN pip install -r /app/requirements.txt

COPY assets /app/assets
COPY templates /app/templates
COPY rickroller.py server.py /app/

ENTRYPOINT ["python", "/app/server.py"]
56 changes: 56 additions & 0 deletions assets/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
:root {
--main-font: monospace;
--main-letter-spacing: -0.5px;
--background: #EFEFEF;
--text-color: #111;

--primary: #333;
--input-background: #F9F9F9; /* #CECECE */
}


body {
font-family: var(--main-font);
letter-spacing: var(--main-letter-spacing);
font-size: 1.3rem;
line-height: 1.3rem;
padding: 10px;
background: var(--background);
color: var(--text-color);
text-align: center;

background-image: url('https://cdn.vox-cdn.com/thumbor/9j-s_MPUfWM4bWdZfPqxBxGkvlw=/1400x1050/filters:format(jpeg)/cdn.vox-cdn.com/uploads/chorus_asset/file/22312759/rickroll_4k.jpg');
background-blend-mode: color-burn;
background-size: cover;
}

form {
margin-top: 3em;
}


input[type=url] {
display: block;
margin: 10pt auto;
background: var(--input-background);
border: none;
font-family: monospace;
font-size: .9em;
color: var(--text-color);
padding: 8px 5px;
outline: none !important;
}

input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:active,
input:-webkit-autofill:focus {
background-color: var(--input-background) !important;
color: var(--text-color) !important;
-webkit-box-shadow: 0 0 0 1000px var(--input-background) inset !important;
-webkit-text-fill-color: var(--text-color) !important;
}

input:-webkit-autofill::first-line {
font-family: var(--main-font) !important;
}
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
flask
beautifulsoup4
requests
validators
58 changes: 58 additions & 0 deletions rickroller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
import re

class RickRoller:

__RICK_ROLL_URL__ = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'

@classmethod
def rickroll(self, url: str) -> str:
soup = self.__get_soup(url)

for a in soup.find('body').find_all('a'):
a.attrs['href'] =self.__RICK_ROLL_URL__

args = [soup, url]
self.__absolutize('link', 'href', *args)
self.__absolutize('script', 'src', *args)
self.__absolutize('img', 'src', *args)

self.__fix_srcset(*args)

return str(soup)

@staticmethod
def __absolutize(tagname, attr, soup, url):
for elt in soup.find_all(tagname, **{attr: True}):
elt.attrs[attr] = urljoin(url, elt.attrs[attr])

@staticmethod
def __fix_srcset(soup, url):
# for responsive images
# e.g. "/static/563761cc22ded851baff4921ecc27649/e4a55/python-url-decode.jpg 256w, /static/563761cc22ded851baff4921ecc27649/36dd4/python-url-decode.jpg 512w, /static/563761cc22ded851baff4921ecc27649/72e01/python-url-decode.jpg 1024w, /static/563761cc22ded851baff4921ecc27649/ac99c/python-url-decode.jpg 1536w, /static/563761cc22ded851baff4921ecc27649/0f98f/python-url-decode.jpg 1920w"
for elt in soup.find_all('img', srcset=True):
srcset = elt.attrs['srcset']

transformed = []
for entry in re.split(" *, *", srcset):
items = re.split(" +", entry)
transformed.append(" ".join([urljoin(url, items[0])] + items[1:]))

elt.attrs['srcset'] = ",".join(transformed)
print(srcset)
print(elt.attrs['srcset'])
print("----")


@staticmethod
def __get_soup(url: str) -> BeautifulSoup:
try:
response = requests.get(url)
if response.status_code != 200:
raise
return BeautifulSoup(response.text, 'html.parser')

except Exception as e:
pass
25 changes: 25 additions & 0 deletions server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from flask import Flask, request, render_template
from validators.url import url as urlvalidate
from rickroller import RickRoller
import urllib

app = Flask(__name__, static_folder='assets')

@app.route('/')
def rickroll():
if (url := request.args.get('u')) is not None:
url = urllib.parse.unquote(url) # may be url-encoded
if not urlvalidate(url):
return f'Invalid URL {url}'

return RickRoller.rickroll(url)

return render_template('index.html')

if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--debug', action='store_true')
args = parser.parse_args()

app.run(host='0.0.0.0', port=8080, debug=args.debug)
30 changes: 30 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!doctype html>

<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title>URL RickRolling</title>
<meta name="description" content="Transform all links into a rick-roll.">
<meta name="author" content="derlin">

<link rel="icon" href="/favicon.ico">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">

<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>

<body>
<h2>Rick Roll Any URL</h2>
<form>
<!--label for="url">Enter an URL and press 'enter'</label-->

<input type="url" name="u" id="url"
placeholder="Enter an URL here and press 'enter'"
pattern="https?://.*\..*" size="100"
required>
</form>
</body>
</html>

0 comments on commit e15f2a1

Please sign in to comment.