Skip to content

bilintechnology/pygmy

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pygmy

Build Status Coverage Status Requirements Status

Live version of this project @ https://pygy.co

Check link stats by adding + to the URL. Example pygy.co/pygmy+

Table of Contents

Pygmy or pygy.co is an open-source, extensible & easy-to-use but powerful URL shortener. It's created keeping in mind that it should be easy to host and run your custom URL shortener without much effort. [Open-source Python URL shortener]

The architecture is very loosely coupled which allows custom integrations easily.

The project has 3 major parts

  • The core URL shortening code
  • A REST API on top. Uses Flask framework
  • The UI layer for rendering the UI. It uses Django framework

Features

  • URL shortner
  • Customized short URL's(ex: pygy.co/pygmy)
  • Support to create auto expiry URL after sometime.
  • Secret key protected URL's
  • User Login/Sign up to track shortned URL's and link stats
  • User dashboard
  • Link Analytics(add + to the tiny URL to get link stats)

Technical Info

  • Python 3, Javascript, JQuery, HTML, CSS
  • REST API: Flask
  • Pyui: Django(It serves the web user interface)
  • DB: PostgreSQL/MySQL/SQLite
  • Others: SQLAlchmey, JWT

Installaton/Setup

  1. Clone git clone https://github.com/amitt001/pygmy.git & cd pygmy
  2. (Optional) Install virtualenv (optional but recommended)
    • pip install virtualenv
    • virtualenv env
    • source env/bin/activate
  3. Install dependencies: pip install -r requirements.txt (if you are using MySQL or PostgreSQL check DB setup section)
  4. cd src
  5. python run.py (It runs Flask and Django servers using gunicorn)
  6. Visit 127.0.0.1:8000 to use the app

Note:

  1. The project has two config files:
    • pygmy.cfg: src/pygmy/config/pygmy.cfg rest API and pygmy core settings file
    • settings.py: src/pyui/pyui/settings.py Django settings file
  2. SQLite is default db, if you are using PostgreSQL or MySQL with this project, make sure they are installed into the system.
  3. To modify config settings vim src/pygmy/config/pygmy.cfg
  4. You can run pygmy shell present in src directory to run the program on terminal. python shell
  5. By default in src/pyui/pyui/settings.py DEBUG is set to True, set it to False in production

DB Setup:

Use MySQL

pip install pymysql

Check correct port:

mysqladmin variables | grep port

Enter below line in src/pygmy/core/pygmy.cfg fro database->url value

mysql+pymysql://root:root@127.0.0.1:3306/pygmy

Enter MySQL URL

CREATE DATABASE pygmy;

Use Postgresql

pip install psycopg2

postgres://amit@127.0.0.1:5432/pygmy

Use SQLite

SQLite is natively supported in Python

sqlite:////var/lib/pygmy/pygmy.db

Using Pygmy API

Create User:

curl -XPOST http://127.0.0.1:9119/api/user/1 -H 'Content-Type: application/json' -d '{
"email": "amit@gmail.com",
"f_name": "Amit",
"l_name": "Tripathi",
"password": "a_safe_one"
}'

Get User:

Get All User Link:

Create Link:

curl -XPOST http://127.0.0.1:9119/api/shorten -H 'Content-Type: application/json' -d '{
"long_url": "http://www.bilintechnology.com/",
"short_code": "custom code, optional",
"is_custom": "True/False, True if short_code is set, optional",
"description": "description, optional",
"secret_key": "custom secret key, optional",
"is_protected": "True/False, True if secret_key is set, optional",
"expire_after": "expire after N minutes, optional"
}'

Response:
{
    "created_at": "04 Apr, 2018 09:03:49",
    "description": null,
    "expire_after": null,
    "hits_counter": 0,
    "id": "http://0.0.0.0:9119/api/link/7",
    "is_custom": false,
    "is_disabled": false,
    "is_protected": false,
    "long_url": "http://www.google.com/?q=123&loc=us&bilin.ext=abcd_u123t34567",
    "owner": null,
    "secret_key": "",
    "short_code": "g",
    "short_url": "http://biin.co",
    "updated_at": "2018-04-04T09:04:10+00:00"
}

Get Link:

curl -XGET -H 'secret_key: xxx' http://127.0.0.1:9119/api/unshorten?url={short_url}

Response:
{
    "created_at": "04 Apr, 2018 08:39:04",
    "description": null,
    "expire_after": null,
    "hits_counter": 2,
    "id": "http://0.0.0.0:9119/api/link/6",
    "is_custom": false,
    "is_disabled": false,
    "is_protected": false,
    "long_url": "http://www.google.com/?q=123&loc=us&bilin.ext=abcd_u123t3456",
    "owner": null,
    "secret_key": "",
    "short_code": "f",
    "short_url": "http://biin.co",
    "updated_at": "2018-04-04T08:39:23+00:00"
}

Shell Usage

Open shell using ./pygmy/src/shell. Available context is pygmy, Config, DB, etc. See all context by using pygmy_context.

Shorten a link:

In [1]: shorten('http://iamit.xyz')
Out[1]:
{'created_at': '15 Nov, 2017 17:33:42',
 'description': None,
 'expire_after': None,
 'hits_counter': 0,
 'id': 'http://0.0.0.0:9119/api/link/5',
 'is_custom': False,
 'is_disabled': False,
 'is_protected': False,
 'long_url': 'http://iamit.xyz',
 'owner': None,
 'secret_key': '',
 'short_code': 'f',
 'short_url': 'http://pygy.co/f',
 'updated_at': '2017-11-15T17:33:42.772520+00:00'}

In [2]: shorten('http://iamit.xyz', request=1)
Out[2]: <pygmy.model.link.Link at 0x105ca1b70>

In [3]: unshorten('f')
Out[3]:
{'created_at': '15 Nov, 2017 17:33:42',
 'description': None,
 'expire_after': None,
 'hits_counter': 0,
 'id': 'http://0.0.0.0:9119/api/link/5',
 'is_custom': False,
 'is_disabled': False,
 'is_protected': False,
 'long_url': 'http://iamit.xyz',
 'owner': None,
 'secret_key': '',
 'short_code': 'f',
 'short_url': 'http://pygy.co/f',
 'updated_at': '2017-11-15T17:33:42.772520+00:00'}

In [4]: link_stats('f')
Out[4]:
{'country_stats': 0,
 'created_at': datetime.datetime(2017, 11, 15, 17, 33, 42, 772520),
 'long_url': 'http://iamit.xyz',
 'referrer': 0,
 'short_code': 'f',
 'time_series_base': None,
 'time_stats': 0,
 'total_hits': 0}

In [5]: # check available context of the shell
In [6]: pygmy_context

In [7]: # Create custom short URL

In [8]: shorten('http://iamit.xyz', short_code='amit')
Out[8]:
{'long_url': 'http://iamit.xyz',
 'short_code': 'amit',
 'short_url': 'http://pygy.co/amit'}

In [9]: shorten?
Signature: shorten(long_url, short_code=None, expire_after=None, description=None, secret_key=None, owner=None, request=None)
Docstring:
    Helper class that has been delegated the task of inserting the
    passed url in DB, base 62 encoding from DB id and return the short
    URL value.

How Link Stats Are Generated?

For getting geo location stats from IP maxminds' GeoLite2-Country.mmd database is used. It's in src/pygmy/app directory.

How Pygmy Auth Token Works?

It uses JWT. When user logs in using username and password two tokens are generated, refresh token and auth token. Auth token is used for authentication with the Pygmy API. Refresh token can only be used to generate new auth token. Auth token has a very short TTL but refresh token has a longer TTL. After 30 minutes. When a request comes with the old auht token and a new token is generated from the refresh token API. User passwords are encrypted by bcrypt hash algorithm.

Development

Run tests and generate a coverage report:

coverage run --source src/pygmy -m py.test

See coverage report:

coverage report

Sponsorship

I would like to thank DigitalOcean for providing initial hosting to Pygmy project. Pygy.co is hosted on DigitalOcean.

License

The MIT license (MIT)

Read License Terms

About

Open-source, feature rich & extensible url shortener + Analytics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 78.6%
  • HTML 15.6%
  • JavaScript 2.4%
  • Shell 1.8%
  • CSS 1.6%