Skip to content

Commit

Permalink
Merge pull request #1 from RyanSept/develop
Browse files Browse the repository at this point in the history
I approve this Merge. Sakabot is free to search and pacify worried minds in Andela.
  • Loading branch information
Ian Otieno authored May 1, 2017
2 parents 27152f5 + 1a065d1 commit 992b8ca
Show file tree
Hide file tree
Showing 12 changed files with 395 additions and 37 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
credentials
config.py

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
worker: python run.py
18 changes: 18 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from pymongo import MongoClient
from slackclient import SlackClient
from app.config import MONGODB, BOT_TOKEN
import pymongo


mongodb_client = MongoClient()
db = mongodb_client[MONGODB]

# db collection
chargers = db.chargers
macbooks = db.macbooks
thunderbolts = db.thunderbolts
lost = db.lost
found = db.found

# slack client
slack_client = SlackClient(BOT_TOKEN)
114 changes: 114 additions & 0 deletions app/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
from app import chargers, macbooks, thunderbolts, lost, found, slack_client


def get_equipment(equipment_id, equipment_type):
'''
Get equipment from database
'''
equipment = None
if equipment_type in ["mac", "tmac", "macbook"]:
equipment = chargers.find_one({"equipment_id": equipment_id})
elif equipment_type in ["charger", "charge", "procharger"]:
equipment = macbooks.find_one({"equipment_id": equipment_id})
elif equipment_type in ["tb", "thunderbolt", "thunder"]:
equipment = thunderbolts.find_one({"equipment_id": equipment_id})

return equipment


def add_lost_equipment(owner, equipment_lost):
'''
Add a lost item to the database
'''
if not lost.find_one({"equipment": equipment_lost}):
slack_profile = slack_client.api_call("users.info",
user=owner)['user']["profile"]

lost_item = {
"equipment": equipment_lost,
"owner": owner,
"email": slack_profile["email"],
"name": '{} {}'.format(slack_profile["first_name"],
slack_profile["last_name"])
}
lost.insert_one(lost_item)
return True
return False


def add_found_equipment(submitter, equipment_found):
'''
Add a found item to the database
'''
if not found.find_one({"equipment": equipment_found}):
slack_profile = slack_client.api_call("users.info",
user=submitter)['user']["profile"]

found_item = {
"equipment": equipment_found,
"submitter": submitter,
"email": slack_profile["email"],
"name": '{} {}'.format(slack_profile["first_name"],
slack_profile["last_name"])
}
found.insert_one(found_item)
return True
return False


def remove_from_lost(equipment):
lost.remove({"equipment": equipment})


def remove_from_found(equipment):
found.remove({"equipment": equipment})


def search_found_equipment(equipment):
return found.find_one({"equipment": equipment})


def search_lost_equipment(equipment):
return lost.find_one({"equipment": equipment})


def notify_user_equipment_found(submitter, equipment_type):
message = "The user <@{}> found your `{}`".format(
submitter, equipment_type)
slack_client.api_call("chat.postMessage", text=message, channel=submitter)


def build_search_reply_atachment(equipment, category):
'''
Returns a slack attachment to show a result
'''
return [{
"text": "That {} belongs to {}".format(category, equipment["fellow_name"]),
"fallback": "Equipment ID - {} | Owner - {}".format(equipment["equipment_id"], equipment["fellow_name"]),
"color": "#4B719C",
"fields": [
{
"title": "Equipment ID",
"value": "{}".format(equipment["equipment_id"]),
"short": "true"
},
{
"title": "Owner",
"value": "{}".format(equipment["fellow_name"]),
"short": "true"
}
]
}]


loading_messages = [
"We're testing your patience.",
"A few bits tried to escape, we're catching them...",
"It's still faster than slacking OPs :stuck_out_tongue_closed_eyes:",
"Loading humorous message ... Please Wait",
"Firing up the transmogrification device...",
"Time is an illusion. Loading time doubly so.",
"Slacking OPs for the information, this could take a while...",
"Loading completed. Press F13 to continue.",
"Oh boy, more work! :face_with_rolling_eyes:..."
]
142 changes: 142 additions & 0 deletions app/handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# coding: UTF-8
import re
import random
import time
import json
from slackbot.bot import respond_to
from app.core import get_equipment, loading_messages, build_search_reply_atachment, add_lost_equipment, search_found_equipment, remove_from_lost, search_lost_equipment, add_found_equipment, notify_user_equipment_found, remove_from_found


@respond_to('hello$|hi$|hey$|aloha$|bonjour$', re.IGNORECASE)
def hello_reply(message):
time.sleep(1)
message.reply('Hello stranger. What can I do you for?')


@respond_to('love', re.IGNORECASE)
def love_reply(message):
love_replies = [
"I know.", ":heart:", "I like you as a friend",
"So does my cousin @slackbot.", "That’s weird. Why do you love 'U'",
"OK, what do you need?"
]
time.sleep(1)
message.reply(random.choice(love_replies))


@respond_to('thanks|thank', re.IGNORECASE)
def gratitude_reply(message):
time.sleep(1)
message.reply("No problemo Guillermo")


@respond_to("(find|get|search|retrieve) (mac|tmac|macbook|charger|charge|procharger|tb|thunderbolt|thunder).*?(\d+)", re.IGNORECASE)
def find_equipment(message, command, equipment_type, equipment_id):
time.sleep(1)
message.reply(random.choice(loading_messages))
time.sleep(2)

attachments = []
equipment_type = equipment_type.strip().lower()
print equipment_type
# get equipment from db
equipment = get_equipment(int(equipment_id), equipment_type)

if equipment:
attachments.extend(
build_search_reply_atachment(equipment,
"item"))
time.sleep(1)
print attachments
message.send_webapi('', json.dumps(attachments))
return
else:
time.sleep(1)
message.reply("We were unable to find an "
"item by the id {} :snowman_without_snow:".format(equipment_id))


@respond_to("lost (mac|tmac|macbook|charger|charge|procharger|tb|thunderbolt|thunder).*?(\d+)")
def report_lost(message, equipment_type, equipment_id):
'''
Report an item has been lost
'''
# get equipment from db
equipment = get_equipment(int(equipment_id), equipment_type)

if equipment:
owner = message.body['user']

# try to find if equipment is in the found collection before adding it
found_equipment = search_found_equipment(equipment)
if found_equipment:
time.sleep(1)
message.reply("Woohoo!:tada: The user <@{}> reported they "
"found your {}.\n"
"We're marking this item as found.".format(
found_equipment['submitter'],
equipment_type))
remove_from_found(found_equipment)
return
else:
if add_lost_equipment(owner, equipment):
time.sleep(1)
message.reply("Added `{}-{}` to our database. We'll slack you "
"in case anyone finds it "
":envelope_with_arrow:".format(equipment_type,
equipment_id))
else:
time.sleep(1)
message.reply("The item `{0}-{1}` is already in our "
"database. Send `found {0} {1}` "
"if you meant to report you found it.".format(
equipment_type,
equipment_id))
else:
time.sleep(1)
message.reply("That item doesn't exist in our database "
"and thus can't be reported as lost.")


@respond_to("found (mac|tmac|macbook|charger|charge|procharger|tb|thunderbolt|thunder).*?(\d+)")
def submit_found(message, equipment_type, equipment_id):
'''
Submit a found item
'''
# get equipment from db
equipment = get_equipment(int(equipment_id), equipment_type)

if equipment:
submitter = message.body['user']
# check if item is in lost collection
equipment_in_lost = search_lost_equipment(equipment)

if equipment_in_lost:
time.sleep(1)
notify_user_equipment_found(submitter, equipment_type)
message.reply("Woohoo!:tada: We've notified the owner <@{}> "
"that you found their {}.\nI would pat your "
"back if I had any hands."
" Keep being awesome :clap:".format(equipment_in_lost["owner"],
equipment_type)
)
remove_from_lost(equipment_in_lost)
else:
if add_found_equipment(submitter, equipment):
time.sleep(1)
message.reply("Added `{}-{}` to our database. We'll slack the "
"owner when they report it missing. "
":outbox_tray:. Thank you".format(equipment_type,
equipment_id))
else:
time.sleep(1)
message.reply("The item `{0}-{1}` is already in our "
"database. Send `lost {0} {1}` "
"if you meant to report you lost it.".format(
equipment_type,
equipment_id))

else:
time.sleep(1)
message.reply("That item doesn't exist in our database "
"and thus can't be reported as found.")
File renamed without changes.
82 changes: 82 additions & 0 deletions app/sprawler/worker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import os
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from pymongo import MongoClient
import pymongo

sheet_list = []
# json credentials you downloaded earlier
rel_path = '/credentials/sakabot-cred.json'
home_dir = os.path.dirname(os.path.abspath(__file__))
CLIENT_SECRET_FILE = home_dir + rel_path
SCOPE = ['https://spreadsheets.google.com/feeds']

# get email and key from creds
cred = ServiceAccountCredentials.from_json_keyfile_name(CLIENT_SECRET_FILE,
SCOPE)

gsheet = gspread.authorize(cred) # authenticate with Google
master_sheet = gsheet.open_by_key(
"1lJ4VUcP1t7kXZNtdVBlfgNDpXVrg--vSlA0iL7H5b4E") # open sheet

macbook_sheet = master_sheet.get_worksheet(0)
charger_sheet = master_sheet.get_worksheet(1)
thunderbolt_sheet = master_sheet.get_worksheet(2)

macbook_data = macbook_sheet.get_all_records()
charger_data = charger_sheet.get_all_records()
thunderbolt_data = thunderbolt_sheet.get_all_records()

macbook_search_data = []
charger_search_data = []
thunderbolt_search_data = []


def populate_search_data(list_of_dictionaries, search_list):
print "Searching", macbook_data, charger_data, thunderbolt_data
for records in list_of_dictionaries:
parsed_data = {records['Andela Code']: records['Fellow Name']}
search_list.append(parsed_data)
return search_list

mongodb_client = MongoClient()
db = mongodb_client['saka']

macbooks = db.macbooks
thunderbolts = db.thunderbolts
chargers = db.chargers

macbooks.create_index([('equipment_id', pymongo.TEXT)], unique=True)
chargers.create_index([('equipment_id', pymongo.TEXT)], unique=True)
thunderbolts.create_index([('equipment_id', pymongo.TEXT)], unique=True)

def store_in_db():
for item in macbook_data:
macbook = {
"equipment_id": int(item['Andela Code'].split("/")[-1]),
"fellow_name": item['Fellow Name'],
"serial_no": item['Device Serial']
}
macbooks.insert_one(macbook)
print "Inserted macbooks"
for item in charger_data:
charger = {
"equipment_id": int(item['Andela Code'].split("/")[-1]),
"fellow_name": item['Fellow Name']
}
chargers.insert_one(charger)

print "Inserted chargers"

for item in thunderbolt_data:
if item['Andela Code']:
thunderbolt = {
"equipment_id": int(item['Andela Code'].split("/")[-1]),
"fellow_name": item['Fellow Name']
}
thunderbolts.insert_one(thunderbolt)

print "Inserted thunderbolts"

if __name__ == "__main__":
store_in_db()
6 changes: 6 additions & 0 deletions config-sample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# slack bot token
API_TOKEN = ""

# text api credentials
AYLIEN_APP_ID = ""
AYLIEN_CLIENT_SECRET = ""
Loading

0 comments on commit 992b8ca

Please sign in to comment.