Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
JeroenHoekstra91 committed Sep 27, 2018
0 parents commit 1fba8af
Show file tree
Hide file tree
Showing 6 changed files with 362 additions and 0 deletions.
106 changes: 106 additions & 0 deletions .gitignore
@@ -0,0 +1,106 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/


19 changes: 19 additions & 0 deletions LICENSE.txt
@@ -0,0 +1,19 @@
Copyright (c) 2018 The Python Packaging Authority

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
48 changes: 48 additions & 0 deletions README.md
@@ -0,0 +1,48 @@
Planga Python Wrapper:
======================

**Setup:**

* Install Twine: `pip install twine`

**requirements:**

* [Python](https://www.python.org/) >= 2.7.x.
* [pip](http://www.pip-installer.org)
* virtualenv (Optional)

**Build and Deploy new package:**

* run `python3 setup.py sdist bdist_wheel`
* run `twine upload --repository-url https://test.pypi.org/legacy/ dist/* --skip-existing`

**Installing the new package:**

* run `python -m pip install jwcrypto`
* run `python -m pip install --index-url https://test.pypi.org/simple/ planga`

Installing jwcrypto manually is only necessary when uploading the planga wrapper to test.pypi.org. The installation tool will attempt to install jwcrypto from test.pypi.org as well, which fails. Having jwcrypto pre-installed allows the installation of the planga wrapper to finish successfully.

**Deploy to live Pypi:**

* run `twine upload dist/* --skip-existing`

For information on how to package for PiPy:
[https://packaging.python.org/tutorials/packaging-projects/](https://packaging.python.org/tutorials/packaging-projects/)

**Example usage:**

```python
from planga import *

conf = PlangaConfiguration(
public_api_id="foobar",
private_api_key="ePxoM3OTkW1z6j84JDurqw",
conversation_id="general",
current_user_id="1234",
current_user_name="Bob",
container_id="my_container_div"
)

snippet = Planga.get_planga_snippet(conf)
```
4 changes: 4 additions & 0 deletions planga/__init__.py
@@ -0,0 +1,4 @@
name = "planga"

from .planga import Planga
from .planga import PlangaConfiguration
66 changes: 66 additions & 0 deletions planga/planga.py
@@ -0,0 +1,66 @@
import re
import json
import uuid
from jwcrypto import jwk, jwe

class Planga(object):
@staticmethod
def get_planga_snippet(configuration):
return """
<script type="text/javascript" src="{}/js/js_snippet.js"></script>
<div id="{}"></div>
<script type="text/javascript" >
new Planga(document.getElementById("{}"), {{
public_api_id: "{}",
encrypted_options: "{}",
socket_location: "{}/socket",
}});
</script>
""".format(
configuration.remote_host,
configuration.container_id,
configuration.container_id,
configuration.public_api_id,
Planga._encrypt_options(configuration),
configuration.remote_host
)

## Private Methods ##

@staticmethod
def _encrypt_options(configuration):
key = jwk.JWK(k=configuration.private_api_key, kty="oct")
protected = {"alg": "A128GCMKW", "enc": "A128GCM"}

payload = json.dumps({
"conversation_id": configuration.conversation_id,
"current_user_id": configuration.current_user_id,
"current_user_name": configuration.current_user_name
})

encryption = jwe.JWE(payload, json.dumps(protected))
encryption.add_recipient(key)
return encryption.serialize(compact=True)

class PlangaConfiguration(object):
def __init__(self, public_api_id=None, private_api_key=None, conversation_id=None,
current_user_id=None, current_user_name=None, container_id=None):

self.public_api_id = public_api_id
self.private_api_key = private_api_key
self.conversation_id = conversation_id
self.current_user_id = current_user_id
self.current_user_name = current_user_name
self.container_id = container_id
self.remote_host = "//planga.def"

if not container_id:
self.container_id = "planga-chat-" + str(uuid.uuid4())

def is_valid(self):
return self._is_alpha(self.public_api_id) and self._is_alpha(self.private_api_key)

### Private Methods ###

def _is_alpha(self, string):
return re.match(r"^[a-zA-Z]+$", string) != None
119 changes: 119 additions & 0 deletions setup.py
@@ -0,0 +1,119 @@
from setuptools import setup, find_packages
from os import path
# io.open is needed for projects that support Python 2.7
# It ensures open() defaults to text mode with universal newlines,
# and accepts an argument to specify the text encoding
# Python 3 only projects can skip this import
from io import open

here = path.abspath(path.dirname(__file__))

# Get the long description from the README file
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = f.read()

# Arguments marked as "Required" below must be included for upload to PyPI.
# Fields marked as "Optional" may be commented out.

setup(
# This is the name of your project. The first time you publish this
# package, this name will be registered for you. It will determine how
# users can install this project, e.g.:
#
# $ pip install sampleproject
#
# And where it will live on PyPI: https://pypi.org/project/sampleproject/
#
# There are some restrictions on what makes a valid project name
# specification here:
# https://packaging.python.org/specifications/core-metadata/#name
name='planga', # Required

# Versions should comply with PEP 440:
# https://www.python.org/dev/peps/pep-0440/
#
# For a discussion on single-sourcing the version across setup.py and the
# project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version='1.0.0', # Required

# This is a one-line description or tagline of what your project does. This
# corresponds to the "Summary" metadata field:
# https://packaging.python.org/specifications/core-metadata/#summary
description='Wrapper for interacting with the Planga chat server.', # Required

# This is an optional longer description of your project that represents
# the body of text which users will see when they visit PyPI.
#
# Often, this is the same as your README, so you can just read it in from
# that file directly (as we have already done above)
#
# This field corresponds to the "Description" metadata field:
# https://packaging.python.org/specifications/core-metadata/#description-optional
long_description=long_description, # Optional

# Denotes that our long_description is in Markdown; valid values are
# text/plain, text/x-rst, and text/markdown
#
# Optional if long_description is written in reStructuredText (rst) but
# required for plain-text or Markdown; if unspecified, "applications should
# attempt to render [the long_description] as text/x-rst; charset=UTF-8 and
# fall back to text/plain if it is not valid rst" (see link below)
#
# This field corresponds to the "Description-Content-Type" metadata field:
# https://packaging.python.org/specifications/core-metadata/#description-content-type-optional
long_description_content_type='text/markdown', # Optional (see note above)

# This should be a valid link to your project's main homepage.
#
# This field corresponds to the "Home-Page" metadata field:
# https://packaging.python.org/specifications/core-metadata/#home-page-optional
url='https://github.com/ResiliaDev/Planga', # Optional

# Classifiers help users find your project by categorizing it.
#
# For a list of valid classifiers, see https://pypi.org/classifiers/
classifiers=[ # Optional
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',

# Indicate who your project is intended for
'Intended Audience :: Developers',

# Pick your license as you wish
'License :: OSI Approved :: MIT License',

# Specify the Python versions you support here. In particular, ensure
# that you indicate whether you support Python 2, Python 3 or both.
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
],

# You can just specify package directories manually here if your project is
# simple. Or you can use find_packages().
#
# Alternatively, if you just want to distribute a single Python file, use
# the `py_modules` argument instead as follows, which will expect a file
# called `my_module.py` to exist:
#
# py_modules=["my_module"],
#
packages=find_packages(exclude=['contrib', 'docs', 'tests']), # Required

# This field lists other packages that your project depends on to run.
# Any package you put here will be installed by pip when your project is
# installed, so they must be valid existing projects.
#
# For an analysis of "install_requires" vs pip's requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=['jwcrypto>=0.5.0'], # Optional

dependency_links=['https://pypi.org/project/jwcrypto/']
)

0 comments on commit 1fba8af

Please sign in to comment.