Skip to content
This repository has been archived by the owner on May 8, 2020. It is now read-only.

Commit

Permalink
Merge pull request #3 from JamesIves/webhook
Browse files Browse the repository at this point in the history
Webhook Version
  • Loading branch information
JamesIves authored Feb 17, 2018
2 parents a467aee + a344f01 commit bbe73b6
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 26 deletions.
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,24 @@ This is a small [Discord](https://discordapp.com/) bot that pushes commits made
This application requires [Python 3.6.1](https://www.python.org/) and the following packages which can be installed with pip.

```
discord.py==0.16.7
requests==2.13.0
```

It also requires the [dhooks module by kyb3r](https://github.com/kyb3r/dhooks) which has been included in the repository.

## How It Works
Every thirty seconds the bot runs a Perforce command in the terminal that checks for the most recent changes. If it finds one it stores it, if the change it finds is the same as the one it gathered previously then it discards it. You'll need to provide the bot with access to your servers Perforce command line. One way of doing this is running the Python application on the server which hosts your Perforce server. If you can type `p4 changes` yourself then the bot will be able to do its thing.


## Configuration
In order to power this bot you'll require a [Discord API bot token]((https://discordapp.com/developers/docs/intro)) and a Discord channel ID that you'd like to post the messages to. These credentials are stored as environment variables.
In order to power this bot you'll require a [Discord Webhook URL]((https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks)) which you can find within the settings menu for a specific channel. The URL should be stored as an environment variable.

| Key | Value Information |
| ------------- | ------------- |
| `DISCORD_BOT_TOKEN` | The token for your Discord bot user, you can sign up for one [here](https://discordapp.com/developers/docs/intro). |
| `DISCORD_CHANNEL_ID` | The ID of the channel you'd like the bot to post its messages to. You can find this by launching the web version of Discord, joining a channel, and then snipping the long number in the URL path. |

| `DISCORD_WEBHOOK_URL` | The [Webhook URL](https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks) for the Discord channel you'd like the bot to post its messages to. |

## Inviting the Bot
Once the application is running you'll need to invite the bot to your Discord server. Replace the `YOUR_CLIENT_ID_HERE` portion of the following URL with the one found in your [Discord API settings](https://discordapp.com/developers/docs/intro). Once connected the bot will make an initial check and then begin re-checking every 30 seconds. The bot doesn't persist data so if you restart the application the bot will post the most recent commit message again.

`https://discordapp.com/oauth2/authorize?&client_id=YOUR_CLIENT_ID_HERE&scope=bot&permissions=0`
## Starting the Bot
Once you've configured the bot, run `$ python app.py` in the terminal and the bot should begin posting the Perfoce servers commit logs to the channel.

![Example](assets/readme.png)
29 changes: 14 additions & 15 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import os
import subprocess
import discord
import asyncio

from settings import *

client = discord.Client()
from discord_hooks import Webhook
from settings import DISCORD_WEBHOOK_URL

# Stores the most recent commit.
global_store = {
Expand All @@ -25,21 +21,24 @@ def check_for_changes():
else:
return ''

@client.event
async def post_changes():
""" Posts the changes to the server """
def post_changes():
""" Posts the changes to the Discord server via a webhook. """
payload = check_for_changes()

if payload != '':
await client.send_message(discord.Object(id='%s') % (DISCORD_CHANNEL_ID), '`%s`' % (payload))
message = Webhook(DISCORD_WEBHOOK_URL, msg='`%s`' % (payload))
message.post()

else:
return

@client.event
async def on_ready():
def init():
""" Initializes a 30 second timer used to check if commits have been made. """
import time
timer = time.time()

while True:
await post_changes()
await asyncio.sleep(30)
post_changes()
time.sleep(30.0 - ((time.time() - timer) % 30.0))

client.run(DISCORD_BOT_TOKEN)
init()
138 changes: 138 additions & 0 deletions discord_hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import json
import requests
import time
import datetime
from collections import defaultdict

class Webhook:
def __init__(self, url, **kwargs):

"""
Initialise a Webhook Embed Object
"""

self.url = url
self.msg = kwargs.get('msg')
self.color = kwargs.get('color')
self.title = kwargs.get('title')
self.title_url = kwargs.get('title_url')
self.author = kwargs.get('author')
self.author_icon = kwargs.get('author_icon')
self.author_url = kwargs.get('author_url')
self.desc = kwargs.get('desc')
self.fields = kwargs.get('fields', [])
self.image = kwargs.get('image')
self.thumbnail = kwargs.get('thumbnail')
self.footer = kwargs.get('footer')
self.footer_icon = kwargs.get('footer_icon')
self.ts = kwargs.get('ts')


def add_field(self,**kwargs):
'''Adds a field to `self.fields`'''
name = kwargs.get('name')
value = kwargs.get('value')
inline = kwargs.get('inline', True)

field = {

'name' : name,
'value' : value,
'inline' : inline

}

self.fields.append(field)

def set_desc(self,desc):
self.desc = desc

def set_author(self, **kwargs):
self.author = kwargs.get('name')
self.author_icon = kwargs.get('icon')
self.author_url = kwargs.get('url')

def set_title(self, **kwargs):
self.title = kwargs.get('title')
self.title_url = kwargs.get('url')

def set_thumbnail(self, url):
self.thumbnail = url

def set_image(self, url):
self.image = url

def set_footer(self,**kwargs):
self.footer = kwargs.get('text')
self.footer_icon = kwargs.get('icon')
ts = kwargs.get('ts')
if ts == True:
self.ts = str(datetime.datetime.utcfromtimestamp(time.time()))
else:
self.ts = str(datetime.datetime.utcfromtimestamp(ts))


def del_field(self, index):
self.fields.pop(index)

@property
def json(self,*arg):
'''
Formats the data into a payload
'''

data = {}

data["embeds"] = []
embed = defaultdict(dict)
if self.msg: data["content"] = self.msg
if self.author: embed["author"]["name"] = self.author
if self.author_icon: embed["author"]["icon_url"] = self.author_icon
if self.author_url: embed["author"]["url"] = self.author_url
if self.color: embed["color"] = self.color
if self.desc: embed["description"] = self.desc
if self.title: embed["title"] = self.title
if self.title_url: embed["url"] = self.title_url
if self.image: embed["image"]['url'] = self.image
if self.thumbnail: embed["thumbnail"]['url'] = self.thumbnail
if self.footer: embed["footer"]['text'] = self.footer
if self.footer_icon: embed['footer']['icon_url'] = self.footer_icon
if self.ts: embed["timestamp"] = self.ts

if self.fields:
embed["fields"] = []
for field in self.fields:
f = {}
f["name"] = field['name']
f["value"] = field['value']
f["inline"] = field['inline']
embed["fields"].append(f)

data["embeds"].append(dict(embed))

empty = all(not d for d in data["embeds"])

if empty and 'content' not in data:
print('You cant post an empty payload.')
if empty: data['embeds'] = []

return json.dumps(data, indent=4)




def post(self):
"""
Send the JSON formated object to the specified `self.url`.
"""

headers = {'Content-Type': 'application/json'}

result = requests.post(self.url, data=self.json, headers=headers)

if result.status_code == 400:
print("Post Failed, Error 400")
else:
print("Payload delivered successfuly")
print("Code : "+str(result.status_code))
time.sleep(2)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
discord.py==0.16.7
requests==2.13.0
3 changes: 1 addition & 2 deletions settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os

# Discord API Settings
DISCORD_BOT_TOKEN = str(os.environ.get('DISCORD_BOT_TOKEN'))
DISCORD_CHANNEL_ID = str(os.environ.get('DISCORD_CHANNEL_ID'))
DISCORD_WEBHOOK_URL = str(os.environ.get('DISCORD_WEBHOOK_URL'))

0 comments on commit bbe73b6

Please sign in to comment.