Skip to content

Commit

Permalink
Merge pull request #3 from AusterweilLab/python-read-config
Browse files Browse the repository at this point in the history
Add config reader for Python, configured for pypi
  • Loading branch information
jeffzemla authored Jul 25, 2017
2 parents afc9ef2 + 30469af commit 25fa60a
Show file tree
Hide file tree
Showing 15 changed files with 353 additions and 39 deletions.
58 changes: 35 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ We have designed two interfaces into jarjar: a shell command and a Python Module

# The Shell Command

The [`sh/`](sh/) directory contains a shell command `jarjar` and a configuration file `.jarjar`.
The `sh/` directory contains a shell command `jarjar` and a configuration file `.jarjar`.

Fill the configuration file out with useful defaults. Critically, you'll want to paste in your Slack webhook so that jarjar knows where to send the message. Then put the configuration file in your home directory (`~/`), that's where jarjar will look for it. Don't worry, you can override those defaults later.
Fill the configuration file out with useful defaults. Critically, you'll want to paste in your Slack webhook so that jarjar knows where to send the message. Then put the configuration file in your home directory (`~/`), that's where jarjar will look for it. Don't worry, you can override those defaults later. Here's a sample `.jarjar`:

```sh
channel="@my_username" # or "#general"
message="Hi! Meesa Jar Jar Binks."
webhook="your-webhook-here"
```

Then, add the `jarjar` _script_ [to your path](https://stackoverflow.com/questions/20054538/add-a-bash-script-to-path). After that, you can use it like so:

Expand Down Expand Up @@ -50,62 +56,68 @@ jarjar -e -u @username -m "Hi!" -w "their-webhook-url"

# The Python Module

This module implements jarjar's functionality more fluidly within Python scripts. Importing the jarjar module provides a simple class, which is initialized by a default webhook and channel (which can be overridden), and sends messages like the shell command.
This module implements jarjar's functionality more fluidly within Python scripts. Importing the jarjar module provides a simple class, which can be used to send messages like the shell command.

Installation is simple:

1. Make sure the [`python/jarjar`](python/) folder is on your current path (e.g., copy it to your working directory, or your modules directory).
2. Make sure you've installed [`python-requests`](http://docs.python-requests.org/en/master/).
1. `pip install jarjar`
2. _Optional_: create a `~/.jarjar` file with some defaults (this is shared with the shell command).

```sh
channel="@my_username" # or "#general"
message="Hi! Meesa Jar Jar Binks."
webhook="your-webhook-here"
```


Then, you're good to go! You can use it as follows:

```python
from jarjar import jarjar

# initialize with defaults
jj = jarjar(channel = '#channel', url = 'slack-webhook-url')
# initialize with defaults from .jarjar
jj = jarjar()

# initialize with custom defaults
jj = jarjar(channel='#channel', webhook='slack-webhook-url')

# initialization is not picky -- provide one or both arguments
jj = jarjar(webhook = 'slack-webhook-url')

# send a text message
jj.text('Hi!')

# send a message to multiple channels or users
jj.text('Hi!',channel=["@jeffzemla","#channel"])
jj.text('Hi!', channel=["@jeffzemla","#channel"])

# send an attachment
jj.attach(dict(status='it\'s all good'))

# send both
jj.post(text='Hi', attach=dict(status='it\'s all good'))

# override defaults
# override defaults after initializing
jj.attach(dict(status='it\'s all good'), channel = '@jeffzemla')
jj.text('Hi!', channel = '@nolan', url = 'another-webhook')

# initialization is not picky
jj = jarjar()
jj.text('Hi', channel = '#channel', url = 'slack-webhook-url')

jj = jarjar(url = 'slack-webhook-url')
jj.attach(dict(status='it\'s all good'), channel = '#channel')
jj.text('Hi!', channel = '@nolan', webhook = 'another-webhook')
```

## Methods

### text
### `text`

> `jj.text(text, **kwargs)`
Send a text message, specified by a string, `text`. User may optionally supply the channel and webhook url in the `kwargs`.
Send a text message, specified by a string, `text`. User may optionally supply the channel and webhook in the `kwargs`.

### attach
### `attach`

> `jj.attach(attach, **kwargs)`
Send attachments, specified by values in a dict, `attach`. User may optionally supply the channel and webhook url in the `kwargs`.
Send attachments, specified by values in a dict, `attach`. User may optionally supply the channel and webhook in the `kwargs`.

### post
### `post`

> `jj.post(text=None, attach=None, channel=None, url=None)`
> `jj.post(text=None, attach=None, channel=None, webhook=None)`
The generic post method. `jj.text(...)` and `jj.attach(...)` are simply convenience functions wrapped around this method. User may supply text and/or attachments, and may override the default channel and webhook url.

Expand Down
7 changes: 7 additions & 0 deletions python/build/lib/jarjar/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from sys import version_info as _version_info

# different importing for python 2 and 3
if _version_info.major == 2:
from jarjar import jarjar
else:
from jarjar.jarjar import jarjar
160 changes: 160 additions & 0 deletions python/build/lib/jarjar/jarjar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import requests
import json
import time
import os
import imp

class jarjar():

def __init__(self, channel=None, webhook=None):

# read config file, set defaults
self._read_config()
self._set_defaults(channel=channel, webhook=webhook)

# headers for post request
self.headers = {'Content-Type': 'application/json'}


def _set_defaults(self, channel=None, webhook=None):
"""
Set the default channel and webhook
This could be a little drier....
"""

# set default channel
if channel is None:
self.default_channel = self.cfg_channel
else:
self.default_channel = channel

# same thing for webhook
if webhook is None:
self.default_webhook = self.cfg_webhook
else:
self.default_webhook = webhook


def _read_config(self):
"""
Read the .jarjar file for defaults.
"""

# get .jarjar path
filename = os.path.join(os.path.expanduser('~'), '.jarjar')

# make empty .jarjar if needed
if not os.path.exists(filename):
open(filename, 'a').close()

# load config
cfg = imp.load_source('_jarjar', filename)

# assign variables
for field in ['channel','webhook']:

# read from config, or set to none
if hasattr(cfg, field):
data = getattr(cfg, field)
else:
data = None

# set value
setattr(self, 'cfg_%s' % field, data)


def _args_handler(self, channel, webhook):
"""
Decide to use the default or provided arguments
"""

# make sure channel and URL are _somewhere_
if [self.default_channel, channel] == [None, None]:
raise Exception('No channel provided!')

if [self.default_webhook, webhook] == [None, None]:
raise Exception('No webhook url provided!')

# use defaults if not overridden
if channel is None: channel = self.default_channel
if webhook is None: webhook = self.default_webhook

return channel, webhook

@staticmethod
def _attachment_formatter(attach):
"""
Convert a dict, fields, into a a correctly-formatted
attachment object for Slack.
"""
attachments = dict(
fallback = "New attachments are ready!",
color = "#36a64f",
ts = time.time(),
fields = []
)

field_array = []
for key in attach:
if isinstance(attach[key], str): outval = attach[key]
else: outval = str(attach[key])
attachments['fields'].append(dict(
title = key,
value = outval,
short = len(outval) < 20
))

return [attachments]

def attach(self, attach, **kwargs):
"""
Send an attachment, without text. This is a wrapper around
self.post
"""
return self.post(attach = attach, **kwargs)

def text(self, text, **kwargs):
"""
Send a message, without attachments. This is a wrapper around
self.post
"""
return self.post(text = text, **kwargs)

def post(self, text=None, attach=None, channel=None, webhook=None):
"""
Generic method to send a message to slack. Defaults may be overridden.
The user may specify text or attachments.
"""

# return if there is nothing to send
if [text, attach] == [None, None]: return None

# get channel and webhook
channel, webhook = self._args_handler(channel, webhook)

# recursively post to all channels in array of channels
if isinstance(channel, list):
status=[]
for c in channel:
status.append(self.post(text=text, attach=attach, channel=c, url=webhook))
return status

# construct a payload
payload = dict(channel = channel)

# add text and attachments if provided
if text is not None:
payload['text'] = text

if attach is not None:
payload['attachments']= self._attachment_formatter(attach)

# convert payload to json and return
payload = json.dumps(payload)
return requests.post(webhook, data=payload, headers=self.headers)

def set_webhook(self, webhook):
self.default_webhook = webhook

def set_channel(self, channel):
self.default_channel = channel
Binary file added python/dist/jarjar-2.0-py2.py3-none-any.whl
Binary file not shown.
Binary file added python/dist/jarjar-2.0.tar.gz
Binary file not shown.
17 changes: 17 additions & 0 deletions python/jarjar.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Metadata-Version: 1.1
Name: jarjar
Version: 2.0
Summary: Programatically send messages to your slack team
Home-page: https://github.com/AusterweilLab/jarjar
Author: The Austerweil Lab at UW-Madison
Author-email: austerweil.lab@gmail.com
License: MIT
Description: UNKNOWN
Keywords: slack,messaging
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
9 changes: 9 additions & 0 deletions python/jarjar.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
setup.cfg
setup.py
jarjar/__init__.py
jarjar/jarjar.py
jarjar.egg-info/PKG-INFO
jarjar.egg-info/SOURCES.txt
jarjar.egg-info/dependency_links.txt
jarjar.egg-info/requires.txt
jarjar.egg-info/top_level.txt
1 change: 1 addition & 0 deletions python/jarjar.egg-info/dependency_links.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions python/jarjar.egg-info/requires.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requests>=2
1 change: 1 addition & 0 deletions python/jarjar.egg-info/top_level.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jarjar
8 changes: 7 additions & 1 deletion python/jarjar/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
from jarjar import jarjar
from sys import version_info as _version_info

# different importing for python 2 and 3
if _version_info.major == 2:
from jarjar import jarjar
else:
from jarjar.jarjar import jarjar
Loading

0 comments on commit 25fa60a

Please sign in to comment.