Advertisement
GoodiesHQ

SuperSimpleURLShortenerAndIPLogger.py

Jun 10th, 2016
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.72 KB | None | 0 0
  1. from twisted.internet import reactor
  2. from twisted.web import resource, server
  3. from random import SystemRandom
  4. from string import ascii_letters, digits
  5. import sqlite3
  6. from time import time
  7. import cgi
  8. from datetime import datetime as dt
  9.  
  10. db_name = "urls.db"
  11. tbl_name = "urls"
  12. log_name = "logs"
  13. URL_LEN = 10  # number of characters to generate URLs from (maximum 20 for CHARACTER type... change to
  14.  
  15. """ For random string generation """
  16. rdev = SystemRandom()
  17. ranstr = lambda n: ''.join(rdev.choice(ascii_letters + digits) for _ in range(n))
  18.  
  19. """ Turns text into and from bytes... aka it bites them """
  20. chomp = lambda s: s.encode() if isinstance(s, str) and not isinstance(s, bytes) else s      # for python2/3 strings
  21. unchomp = lambda s: s.decode() if isinstance(s, bytes) and not isinstance(s, str) else s    # for python2/3 strings
  22. to_time = lambda t:  dt.fromtimestamp(float(t)).strftime("%d %b %Y, %H:%M:%S")
  23. base_url = lambda u: '/'.join(u.split("/")[:3])
  24.  
  25.  
  26. class IPLoggerUtils:
  27.     def __init__(self):
  28.         self.con = sqlite3.connect(db_name)
  29.         self.cur = self.con.cursor()
  30.         drop = True  # If this is true, then every time you run the program, it will erase all of the logs/ID's
  31.         if drop:
  32.             sql1 = "DROP TABLE IF EXISTS {}".format(tbl_name)
  33.             sql2 = "DROP TABLE IF EXISTS {}".format(log_name)
  34.             self.exec_commit(sql1, sql2)
  35.         sql1 = "CREATE TABLE IF NOT EXISTS {} (url_id CHARACTER, redirect_url TEXT)".format(tbl_name)
  36.         sql2 = "CREATE TABLE IF NOT EXISTS {} (url_id CHARACTER, ip CHARACTER, stamp DATE)".format(log_name)
  37.         self.exec_commit(sql1, sql2)
  38.  
  39.     def exec_commit(self, *commands):
  40.         for sql in commands:
  41.             self.cur.execute(sql)
  42.             self.con.commit()
  43.  
  44.     def get_logs(self, url_id):
  45.         url_id = unchomp(url_id)
  46.         self.cur.execute("SELECT * FROM {} WHERE url_id=?".format(log_name), (url_id,))
  47.         rows = self.cur.fetchall()
  48.         return len(rows) > 0, rows
  49.  
  50.     def create_url(self, url):
  51.         url = unchomp(url)
  52.         r = unchomp(ranstr(URL_LEN))
  53.         while self.shorturl_exists(r)[0]:
  54.             r = unchomp(ranstr(URL_LEN))
  55.         self.cur.execute("INSERT INTO {} VALUES (?, ?)".format(tbl_name), (r, url))
  56.         self.con.commit()
  57.         return r
  58.  
  59.     def shorturl_exists(self, url_id):
  60.         url_id = unchomp(url_id)
  61.         self.cur.execute("SELECT * FROM {} WHERE url_id=?".format(tbl_name), (url_id,))
  62.         row = self.cur.fetchone()
  63.         return row is not None, row
  64.  
  65.     def log_ip(self, url_id, ip):
  66.         url_id = unchomp(url_id)
  67.         self.cur.execute("INSERT INTO {} VALUES (?, ?, ?)".format(log_name), (url_id, ip, time()))
  68.         self.con.commit()
  69.  
  70.     def all_logs(self):
  71.         self.cur.execute("SELECT * FROM {}".format(log_name))
  72.         return self.cur.fetchall()
  73.  
  74. utils = IPLoggerUtils()
  75.  
  76.  
  77. class Redirect(resource.Resource):
  78.     """Attempts to redirect with HTTP meta tags. If that fails, it tries JS. If that fails, it just returns a link"""
  79.     redirect_html = """
  80.    <!DOCTYPE html>
  81.    <html lang="en">
  82.    <head>
  83.        <title>URL Redirect</title>
  84.        <meta http-equiv="Refresh" content="0; URL={}">
  85.        <script type="text/javascript">
  86.            window.location.href = "{}"
  87.        </script>
  88.    </head>
  89.    <body>
  90.        <p>If you are not redirected, please click <a href="{}">here</a> to continue.</p>
  91.    </body>
  92.    </html>
  93.    """
  94.  
  95.     def __init__(self, url):
  96.         self.url = url
  97.         super().__init__()
  98.  
  99.     def render_GET(self, request):
  100.         return chomp(self.redirect_html.format(self.url, self.url, self.url))
  101.  
  102.  
  103. class IPLogger(resource.Resource):
  104.     def getChild(self, path, request):
  105.         in_db, row = utils.shorturl_exists(path)
  106.         if in_db:
  107.             peer = request.transport.getPeer()
  108.             utils.log_ip(path, peer.host)
  109.             return Redirect(row[1])
  110.         return resource.NoResource(message="Sorry, that shortened URL does not exist.")
  111.  
  112.     def render_GET(self, request):
  113.         return chomp("Hi")
  114.  
  115.  
  116. class Log(resource.Resource):
  117.     def __init__(self, url_id):
  118.         self.url_id = unchomp(url_id)
  119.  
  120.     def render_GET(self, request):
  121.         in_db, rows = utils.get_logs(self.url_id)
  122.         if in_db:
  123.             ret = '\n'.join("{} - {} - {}".format(row[0], row[1], to_time(row[2])) for row in rows)
  124.             return chomp(ret)
  125.         return chomp("That ID has not been logged.")
  126.  
  127.  
  128. class IPLogViewer(resource.Resource):
  129.     def getChild(self, path, request):
  130.         return Log(path)
  131.  
  132.     def render_GET(self, request):
  133.         return chomp("Look for an ID. /log/&lt;your id&gt;")
  134.  
  135.  
  136. class IPLogCreate(resource.Resource):
  137.     def render_GET(self, reqest):
  138.         return chomp("""
  139.        <!DOCTYPE html>
  140.        <html lang="en">
  141.        <head>
  142.            <meta charset="UTF-8">
  143.            <title>URL IP Logger</title>
  144.        </head>
  145.        <body>
  146.        <form action="" method="post">
  147.            Redirect URL:<br>
  148.            <input name="url" type="text" size="100%"><br>
  149.            <input type="submit" value="Create URL" name="submit">
  150.        </form>
  151.        </body>
  152.        </html>
  153.        """)
  154.  
  155.     def render_POST(self, request):
  156.         burl = base_url(str(request.URLPath()))
  157.         url = unchomp(request.args.get(b"url", b"")[0])
  158.         if url != "":
  159.             url_id = utils.create_url(url)
  160.             return chomp("Direct users to {}/{} - View logs at {}/log/{}".format(burl, url_id, burl, url_id))
  161.  
  162. logger = IPLogger()
  163. logger.putChild(chomp("log"), IPLogViewer())
  164. logger.putChild(chomp("new"), IPLogCreate())
  165. logger.putChild(chomp(""), Redirect("new"))
  166. fac = server.Site(logger)
  167. reactor.listenTCP(8080, fac)
  168. reactor.run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement