diff --git a/links/__init__.py b/links/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/links/admin.py b/links/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/links/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/links/migrations/0001_initial.py b/links/migrations/0001_initial.py
new file mode 100644
index 0000000..f092cd3
--- /dev/null
+++ b/links/migrations/0001_initial.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Link',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('link', models.URLField(max_length=2048)),
+ ('base62', models.CharField(max_length=64, null=True)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('clicks', models.IntegerField(default=0)),
+ ('ip', models.GenericIPAddressField(null=True)),
+ ],
+ options={
+ },
+ bases=(models.Model,),
+ ),
+ ]
diff --git a/links/migrations/0002_auto_20150117_2248.py b/links/migrations/0002_auto_20150117_2248.py
new file mode 100644
index 0000000..8f1a83d
--- /dev/null
+++ b/links/migrations/0002_auto_20150117_2248.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('links', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='link',
+ name='id',
+ field=models.AutoField(serialize=False, primary_key=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/links/migrations/0003_auto_20150117_2306.py b/links/migrations/0003_auto_20150117_2306.py
new file mode 100644
index 0000000..86fff71
--- /dev/null
+++ b/links/migrations/0003_auto_20150117_2306.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('links', '0002_auto_20150117_2248'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='link',
+ name='base62',
+ ),
+ migrations.AlterField(
+ model_name='link',
+ name='id',
+ field=models.CharField(max_length=12, serialize=False, primary_key=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/links/migrations/0004_auto_20150117_2338.py b/links/migrations/0004_auto_20150117_2338.py
new file mode 100644
index 0000000..46e64c5
--- /dev/null
+++ b/links/migrations/0004_auto_20150117_2338.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('links', '0003_auto_20150117_2306'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='link',
+ old_name='link',
+ new_name='url',
+ ),
+ ]
diff --git a/links/migrations/__init__.py b/links/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/links/models.py b/links/models.py
new file mode 100644
index 0000000..f99f7e2
--- /dev/null
+++ b/links/models.py
@@ -0,0 +1,54 @@
+from django.db import models
+from django.forms import ModelForm, CharField, TextInput
+import random
+
+
+class Link(models.Model):
+ id = models.CharField(primary_key=True, max_length=12)
+ url = models.URLField(max_length=2048)
+ created_at = models.DateTimeField(auto_now_add=True)
+ clicks = models.IntegerField(default=0)
+ ip = models.GenericIPAddressField(null=True)
+
+ def __unicode__(self):
+ return self.url
+
+ def generate_unique_id(self, length=12):
+ attempts = 0
+ id = random_id()
+ try:
+ while Link.objects.get(id=id) and attempts < 10:
+ attempts = attempts + 1
+ id = random_id()
+ except:
+ pass
+ return id
+
+ def save(self, *args, **kwargs):
+ if not self.pk:
+ self.id = self.generate_unique_id()
+ super(Link, self).save(*args, **kwargs)
+
+
+class LinkForm(ModelForm):
+ url = CharField(label='')
+ class Meta:
+ model = Link
+ fields = ['url']
+
+
+def random_id():
+ rand = ''
+ for i in range(0,12):
+ rand += int_to_char(random.randint(0,61));
+ return rand;
+
+
+def int_to_char(int):
+ if(int < 10):
+ char = chr(int + 48)
+ elif(int < 36):
+ char = chr(int + 55)
+ else:
+ char = chr(int + 61)
+ return char
\ No newline at end of file
diff --git a/links/templates/index.html b/links/templates/index.html
new file mode 100644
index 0000000..07fa317
--- /dev/null
+++ b/links/templates/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+
+ minie links!
+
+
+
+
+
+
+
+

+
+ {% if short_url %}
+
+ {% endif %}
+
Drag this bookmarklet
min.ie to your bookmark bar, or just stick "min.ie/" before any link you want to shrink.
+
Django and Postgres Powered
+
+
+
+
+
+
\ No newline at end of file
diff --git a/links/tests.py b/links/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/links/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/links/views.py b/links/views.py
new file mode 100644
index 0000000..8d3f551
--- /dev/null
+++ b/links/views.py
@@ -0,0 +1,26 @@
+from django.shortcuts import render, redirect
+from django.http import Http404
+from .models import Link, LinkForm
+from urlparse import urlparse
+
+def catchall(request, id):
+ try:
+ link = Link.objects.get(id=id)
+ return redirect(link.url)
+ except:
+ parsed = urlparse(id)
+ if parsed.netloc:
+ link = Link(url=id)
+ link.save();
+ context = {'form': LinkForm}
+ context['short_url'] = "http://" + str(request.get_host()) + "/" + str(link.id)
+ return render(request, 'index.html', context)
+ raise Http404("Link does not exist")
+
+def home(request):
+ context = {'form': LinkForm}
+ if 'link' in request.POST:
+ link = Link(link=request.POST['url'])
+ link.save();
+ context['short_url'] = "http://" + str(request.get_host()) + "/" + str(link.id)
+ return render(request, 'index.html', context)
\ No newline at end of file
diff --git a/minie/settings.py b/minie/settings.py
index e96b364..25fbf8e 100644
--- a/minie/settings.py
+++ b/minie/settings.py
@@ -17,7 +17,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DEBUG = True
TEMPLATE_DEBUG = True
-SECRET_KEY = 'uz+*54ipcwwpjjwkt+hb4o_7y0o-%6=@+$rmm2yoaw_7j_=vjw'
+SECRET_KEY = os.environ['SECRET_KEY']
ALLOWED_HOSTS = ['*']
@@ -30,16 +30,17 @@ INSTALLED_APPS = (
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'links',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+)
+
+TEMPLATE_DIRS = (
+ os.path.join(BASE_DIR, 'links/templates'),
)
ROOT_URLCONF = 'minie.urls'
diff --git a/minie/urls.py b/minie/urls.py
index f1beb5a..e158d95 100644
--- a/minie/urls.py
+++ b/minie/urls.py
@@ -5,6 +5,7 @@ urlpatterns = patterns('',
# Examples:
# url(r'^$', 'minie.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
-
+ url(r'^$', 'links.views.home', name='home'),
url(r'^admin/', include(admin.site.urls)),
+ url(r'(.*)', 'links.views.catchall', name='short'),
)
diff --git a/static/minie.png b/static/minie.png
new file mode 100644
index 0000000..916439a
Binary files /dev/null and b/static/minie.png differ
diff --git a/static/style.css b/static/style.css
new file mode 100644
index 0000000..f255595
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1,229 @@
+/***** Global Settings *****/
+
+html, body {
+border:0;
+margin:0;
+padding:0;
+}
+
+body {
+font:100%/1.25 arial, helvetica, sans-serif;
+}
+
+/***** Common Formatting *****/
+
+h1, h2, h3, h4, h5, h6 {
+margin:0;
+padding:0;
+font-weight:normal;
+}
+
+h1 {
+padding:30px 0 25px 0;
+letter-spacing:-1px;
+font:2em arial, helvetica, sans-serif;
+}
+
+h2 {
+padding:20px 0;
+letter-spacing:-1px;
+font:1.5em arial, helvetica, sans-serif;
+}
+
+h3 {
+font:1em arial, helvetica, sans-serif;
+font-weight:bold;
+}
+
+p, ul, ol {
+margin:0;
+padding:0 0 15px 0;
+}
+
+ul, ol {
+list-style: disc;
+padding:0 0 15px 25px;
+}
+
+blockquote {
+margin:22px 40px;
+padding:0;
+}
+
+small {
+font-size:0.85em;
+}
+
+img {
+border:0;
+}
+
+sup {
+position:relative;
+bottom:0.3em;
+vertical-align:baseline;
+}
+
+sub {
+position:relative;
+bottom:-0.2em;
+vertical-align:baseline;
+}
+
+acronym, abbr {
+cursor:help;
+letter-spacing:1px;
+border-bottom:1px dashed;
+}
+
+/***** Links *****/
+
+a, a:visited {
+text-decoration:none;
+}
+
+/***** Forms *****/
+
+form {
+margin:0;
+padding:0;
+display:inline;
+}
+
+input, select, textarea {
+font:1em arial, helvetica, sans-serif;
+}
+
+textarea {
+line-height:1.25;
+}
+
+label {
+cursor:pointer;
+}
+
+/***** Tables *****/
+
+table {
+border:0;
+margin:0 0 18px 0;
+padding:0;
+}
+
+ table tr td {
+ padding:2px;
+ }
+
+/***** Wrapper *****/
+
+#wrap {
+width:660px;
+margin:0 auto;
+}
+
+/***** Global Classes *****/
+
+.clear { clear:both; }
+
+.float-left { float:left; }
+.float-right { float:right; }
+
+.text-left { text-align:left; }
+.text-right { text-align:right; }
+.text-center { text-align:center; }
+.text-justify { text-align:justify; }
+
+.bold { font-weight:bold; }
+.italic { font-style:italic; }
+.underline { border-bottom:1px solid; }
+.highlight { background:#ffc; }
+
+.wrap { width:960px;margin:0 auto; }
+
+.img-left { float:left;margin:4px 10px 4px 0; }
+.img-right { float:right;margin:4px 0 4px 10px; }
+
+.nopadding { padding:0; }
+.noindent { margin-left:0;padding-left:0; }
+.nobullet { list-style:none;list-style-image:none; }
+
+body{
+ color: #666;
+ font-size: 16px;
+}
+input {
+ line-height: 24px;
+}
+#main-submit{
+ background: #ff3139;
+ color: #FFF;
+ line-height: 22px;
+ border-bottom: #b92329 solid 1px;
+ border-right: #b92329 solid 1px;
+ border-top: #ff3139 solid 1px;
+ border-left: #ff3139 solid 1px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ font-size: 1.2em;
+}
+#main-submit:active{
+ border-bottom: #ff3139 solid 1px;
+ border-right: #ff3139 solid 1px;
+ border-top: #b92329 solid 1px;
+ border-left: #b92329 solid 1px;
+}
+#main-box{
+ background: #4e9bd1;
+ width: 570px;color: #FFF;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ border-bottom: #3d79a3 solid 1px;
+ border-right: #3d79a3 solid 1px;
+ border-top: #4e9bd1 solid 1px;
+ border-left: #4e9bd1 solid 1px;
+ margin: 0 auto;
+ margin-top: 20px;
+ text-align: center;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+}
+#logo-wrap{
+ width: 570px;
+ margin: 0 auto;
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+#logo-wrap p{
+ text-align: right;
+ font-size: 10px;
+ color: #ddd;
+}
+#logo{
+ float:right;
+}
+#info{
+ padding-top:15px;
+ clear:both;
+ line-height: 24px;
+}
+#info a{
+ color: #4e9bd1;
+ padding: 4px 8px;
+ background: #EEE;
+ border-bottom: #CCC solid 1px;
+ border-right: #CCC solid 1px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+}
+
+form ul {
+ padding: 0;
+}
+
+form li {
+ display: inline;
+}
+
+#id_url {
+ width: 400px;
+}
\ No newline at end of file