Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
|
bafb1c5e68 | ||
|
d9d763a1d1 | ||
|
e37aa4bb13 |
5 changed files with 71 additions and 60 deletions
|
@ -1 +1,2 @@
|
||||||
|
-r requirements.txt
|
||||||
setuptools-git
|
setuptools-git
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
pyyaml
|
pyyaml
|
||||||
cloudant
|
cloudant
|
||||||
aiohttp
|
flask
|
||||||
aiohttp-jinja2
|
|
||||||
trafaret
|
trafaret
|
||||||
|
|
|
@ -27,6 +27,7 @@ def main() -> None:
|
||||||
"""
|
"""
|
||||||
parser = argument_parse()
|
parser = argument_parse()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
debug = True if args.verbose > 0 else False
|
||||||
verbosity_level = verbosity(args.verbose)
|
verbosity_level = verbosity(args.verbose)
|
||||||
setup_logging(args.logger, verbosity_level)
|
setup_logging(args.logger, verbosity_level)
|
||||||
config = Config(CONFIGURATION).get_config()
|
config = Config(CONFIGURATION).get_config()
|
||||||
|
@ -36,9 +37,8 @@ def main() -> None:
|
||||||
with DB(db_config) as db:
|
with DB(db_config) as db:
|
||||||
db.initialize_shortenit()
|
db.initialize_shortenit()
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
handler = SiteHandler(db, shorten_url, lenghten_url)
|
handler = SiteHandler(db, shorten_url, lenghten_url)
|
||||||
web = Web(loop, handler)
|
web = Web(handler, debug=debug)
|
||||||
web.host = server_config.get('host', None)
|
web.host = server_config.get('host', None)
|
||||||
web.port = server_config.get('port', None)
|
web.port = server_config.get('port', None)
|
||||||
web.start_up()
|
web.start_up()
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.4/clipboard.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
data: JSON.stringify({'url' : $('#url-input').val(),
|
data: JSON.stringify({'url' : $('#url-input').val(),
|
||||||
'timestamp': Date.now()}),
|
'timestamp': Date.now()}),
|
||||||
success: returnSuccess,
|
success: returnSuccess,
|
||||||
|
error: returnFailure,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
});
|
});
|
||||||
|
@ -41,28 +43,36 @@
|
||||||
|
|
||||||
function returnSuccess(data, textStatus, jqXHR) {
|
function returnSuccess(data, textStatus, jqXHR) {
|
||||||
var url = href.concat(data.url);
|
var url = href.concat(data.url);
|
||||||
console.log(window.location.href)
|
console.log(href)
|
||||||
if(data.url) {
|
if(data.url) {
|
||||||
document.getElementById("url-result").value = url;
|
document.getElementById("url-result").value = url;
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("url-result").value = "Please enter a valid URL!";
|
document.getElementById("url-result").value = "The URL was too short and somehow got lost on the way, please try generating a new one.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyToClipboard() {
|
function returnFailure(data, textStatus, jqXHR) {
|
||||||
/* Get the text field */
|
document.getElementById("url-result").value = "Please enter a valid URL!";
|
||||||
var copyText = document.querySelector("#url-result");
|
}
|
||||||
|
|
||||||
/* Select the text field */
|
window.onload=function() {
|
||||||
copyText.select();
|
console.log(ClipboardJS.isSupported())
|
||||||
copyText.setSelectionRange(0, 99999); /*For mobile devices*/
|
var clipboard = new ClipboardJS('.btn', {
|
||||||
|
container: document.getElementById('copy-button')
|
||||||
|
});
|
||||||
|
|
||||||
/* Copy the text inside the text field */
|
clipboard.on('success', function(e) {
|
||||||
document.execCommand("copy");
|
console.info('Action:', e.action);
|
||||||
|
console.info('Text:', e.text);
|
||||||
|
console.info('Trigger:', e.trigger);
|
||||||
|
});
|
||||||
|
|
||||||
|
clipboard.on('error', function(e) {
|
||||||
|
console.error('Action:', e.action);
|
||||||
|
console.error('Trigger:', e.trigger);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/* Alert the copied text */
|
|
||||||
alert("Copied the text: " + copyText.value);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -98,7 +108,8 @@
|
||||||
<input type="text" id="url-result" class="form-control" readonly>
|
<input type="text" id="url-result" class="form-control" readonly>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<button class="btn btn-outline-primary" type="button" id="copy-button" data-toggle="tooltip" onclick="copyToClipboard()" data-placement="button" title="Copy to Clipboard">Copy</button>
|
<div>
|
||||||
|
<button class="btn btn-outline-primary" data-clipboard-target="#url-result" data-clipboard-action="copy">Copy</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1,47 +1,40 @@
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import aiohttp_jinja2
|
|
||||||
import jinja2
|
|
||||||
|
|
||||||
import trafaret as t
|
import trafaret
|
||||||
|
|
||||||
from aiohttp import web
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from flask import Flask
|
||||||
|
from flask import render_template
|
||||||
|
from flask import request
|
||||||
|
from flask import redirect
|
||||||
|
from flask import abort
|
||||||
|
|
||||||
|
|
||||||
class Web:
|
class Web:
|
||||||
def __init__(self, loop, handler):
|
def __init__(self, handler, debug=False):
|
||||||
self.logger = logging.getLogger(self.__class__.__name__)
|
self.logger = logging.getLogger(self.__class__.__name__)
|
||||||
self.loop = loop
|
|
||||||
self.app = None
|
self.app = None
|
||||||
self.host = None
|
self.host = None
|
||||||
self.port = None
|
self.port = None
|
||||||
self.handler = handler
|
self.handler = handler
|
||||||
self.router = None
|
self.debug = debug
|
||||||
self.loader = None
|
|
||||||
|
|
||||||
def start_up(self):
|
def start_up(self):
|
||||||
self.loop.run_until_complete(self.init())
|
self.init()
|
||||||
web.run_app(self.app, host=self.host, port=self.port)
|
self.app.run(host=self.host, port=self.port, debug=self.debug)
|
||||||
|
|
||||||
async def init(self):
|
def init(self):
|
||||||
self.app = web.Application(loop=self.loop)
|
self.app = Flask(__name__)
|
||||||
templates = Path(__file__).absolute().parent.parent.joinpath('templates')
|
|
||||||
|
|
||||||
self.loader = jinja2.FileSystemLoader(str(templates))
|
|
||||||
self.logger.debug(str(templates))
|
|
||||||
aiohttp_jinja2.setup(self.app,
|
|
||||||
loader=self.loader)
|
|
||||||
self.setup_routes()
|
self.setup_routes()
|
||||||
|
|
||||||
def setup_routes(self):
|
def setup_routes(self):
|
||||||
self.router = self.app.router
|
self.app.add_url_rule('/', '/', self.handler.index,
|
||||||
self.router.add_get('/', self.handler.index,
|
methods=['GET'])
|
||||||
name='index')
|
self.app.add_url_rule('/shortenit', '/shortenit', self.handler.shortenit,
|
||||||
self.router.add_post('/shortenit', self.handler.shortenit,
|
methods=['POST'])
|
||||||
name='shortenit')
|
self.app.add_url_rule('/<identifier>', '/identifier', self.handler.short_redirect,
|
||||||
self.router.add_get('/{identifier}', self.handler.redirect,
|
methods=['GET'])
|
||||||
name='redirect')
|
|
||||||
|
|
||||||
|
|
||||||
class SiteHandler:
|
class SiteHandler:
|
||||||
|
@ -50,29 +43,36 @@ class SiteHandler:
|
||||||
self.database = database
|
self.database = database
|
||||||
self.shorten_url = shorten_url
|
self.shorten_url = shorten_url
|
||||||
self.lenghten_url = lenghten_url
|
self.lenghten_url = lenghten_url
|
||||||
self.shortenit_load_format = t.Dict({
|
self.shortenit_load_format = trafaret.Dict({
|
||||||
t.Key('url'): t.URL,
|
trafaret.Key('url'): trafaret.URL,
|
||||||
t.Key('timestamp'): t.Int
|
trafaret.Key('timestamp'): trafaret.Int
|
||||||
})
|
})
|
||||||
|
|
||||||
async def shortenit(self, request):
|
def shortenit(self):
|
||||||
data = await request.json()
|
data = request.get_json()
|
||||||
self.logger.debug(data)
|
|
||||||
try:
|
try:
|
||||||
data = self.shortenit_load_format(data)
|
data = self.shortenit_load_format(data)
|
||||||
except t.DataError:
|
except Exception as e:
|
||||||
raise web.HTTPBadRequest('URL is not valid')
|
self.logger.error(e)
|
||||||
short_url = self.shorten_url(self.database, data['url'], data['timestamp'])
|
return {}, 400
|
||||||
|
self.logger.error(e)
|
||||||
|
abort(400)
|
||||||
|
try:
|
||||||
|
short_url = self.shorten_url(
|
||||||
|
self.database, data['url'], data['timestamp'])
|
||||||
|
except KeyError as e:
|
||||||
|
self.logger.error(e)
|
||||||
|
abort(400)
|
||||||
self.logger.debug(short_url)
|
self.logger.debug(short_url)
|
||||||
return web.json_response({"url": short_url})
|
return {"url": short_url}
|
||||||
|
|
||||||
async def redirect(self, request):
|
def short_redirect(self, identifier):
|
||||||
identifier = request.match_info['identifier']
|
|
||||||
url = self.lenghten_url(self.database, identifier)
|
url = self.lenghten_url(self.database, identifier)
|
||||||
|
self.logger.debug("The URL is...")
|
||||||
|
self.logger.debug(url)
|
||||||
if not url:
|
if not url:
|
||||||
raise web.HTTPNotFound()
|
abort(404)
|
||||||
return web.HTTPFound(location=url)
|
return redirect(url)
|
||||||
|
|
||||||
@aiohttp_jinja2.template('index.html')
|
def index(self):
|
||||||
async def index(self, request):
|
return render_template('index.html')
|
||||||
return {}
|
|
||||||
|
|
Loading…
Reference in a new issue