<file_sep>from schematics.models import Model
from schematics.types import StringType


class PostbackButton(Model):
    type = StringType(required=True, choices=['postback'], default='postback')
    title = StringType(required=True, max_length=20)
    payload = StringType(required=True, max_length=1000)
<file_sep>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import types

from io import StringIO
from os import path as op
from os.path import join
from textwrap import dedent

from setuptools import (
    setup,
    find_packages,
)
from setuptools.command.test import test as TestCommand


def _read(filename):
    try:
        fp = open(join(op.dirname(__file__), filename))
        try:
            return fp.read()
        finally:
            fp.close()
    except (IOError, OSError):  # IOError/2.7, OSError/3.5
        return str()


def _read_requirements(filename):
    is_valid = lambda _: _ and not any(_.startswith(ch) for ch in ['#', '-'])

    data = getattr(types, 'UnicodeType', str)(_read(filename))
    return list((_.strip() for _ in StringIO(data) if is_valid(_.strip())))


class PyTest(TestCommand):
    user_options = [('pytest-args=', 'a', "Arguments to pass to pytest")]

    def initialize_options(self):
        TestCommand.initialize_options(self)
        self.pytest_args = []

    def run_tests(self):
        # Import here, cause outside the eggs aren't loaded.
        import pytest

        errno = pytest.main(self.pytest_args)
        sys.exit(errno)


setup_params = dict(
    name="botics",
    version='0.1.0',
    description="Python package skeleton.",
    long_description=dedent("""
        The boilerplate Python project that aims to create facility for maintaining of
        the package easily. It considering tools for building, testing and distribution.
        """).strip(),
    author="<NAME>",
    author_email='<EMAIL>',
    url='https://waldo.foobar.org',

    classifiers=dedent("""
        Natural Language :: English
        Development Status :: 1 - Planning
        Operating System :: POSIX :: Linux
        Programming Language :: Python
        Programming Language :: Python :: 3.5
        """),
    license='BSD3',
    keywords=[],

    packages=find_packages(),
    include_package_data=True,
    zip_safe=False,


    install_requires=_read_requirements('requirements.txt'),
    setup_requires=[
        'wheel',
    ],
    tests_require=_read_requirements('requirements-test.txt'),

    cmdclass={'test': PyTest},
)


def main():
    setup(**setup_params)


if __name__ == '__main__':
    main()
<file_sep>import logging
import logging.config
import os

import yaml


def config_logging(config_file='logging.yaml', level=logging.INFO):
    '''
    Configures the logger based on a yaml config file

    # Arguments
    config_file: yaml config file containing the settings
    level: default logging level

    # Returns
    a configures logger
    '''
    if os.path.exists(config_file):
        with open(config_file, 'rt') as f:
            config = yaml.safe_load(f.read())
        logging.config.dictConfig(config)
    else:
        logging.basicConfig(level=level)


config_logging(level=logging.DEBUG)
<file_sep># -*- coding: utf-8 -*-
"""Sender Actions

Set typing indicators or send read receipts using the Send API,
to let users know you are processing their request.

"""
from schematics.models import Model
from schematics.types import StringType


class SenderAction(Model):
    sender_action = StringType(required=True,
                               choices=['mark_seen',
                                        'typing_on',
                                        'typing_off'])
<file_sep>from botics.client import Client
from unittest import TestCase
import pytest
import os

ACCESS_TOKEN = os.environ.get('ACCESS_TOKEN', None)
RECIPIENT_ID = os.environ.get('RECIPIENT_ID', None)


class SendActionTest(TestCase):
    def setUp(self):
        self.client = Client(page_access_token=ACCESS_TOKEN)

    def test_foo(self):
        self.client.send_action(recipient_id=RECIPIENT_ID,
                                sender_action="typing_on")
        self.client.send_text_message(recipient_id=RECIPIENT_ID,
                                      text="hello")


if __name__ == '__main__':
    pytest.main()
<file_sep>from schematics.models import Model
from schematics.types import StringType
from schematics.types.compound import ListType, ModelType

from generic_attachment import GenericAttachment
from quick_reply import QuickReply


class QuickReplyMessage(Model):
    text = StringType(required=False)
    quick_replies = ListType(ModelType(QuickReply), required=False,
                             max_size=10)
    attachment = ModelType(GenericAttachment, required=False)
<file_sep>from schematics.models import Model
from schematics.types import StringType


class Recipient(Model):
    id = StringType(required=True)
<file_sep>flask
gunicorn
gevent
schematics==1.1.1
<file_sep>from schematics.models import Model
from schematics.types import StringType
from schematics.types.compound import ListType, ModelType

from postback_button import PostbackButton


class GenericElement(Model):
    title = StringType(required=True, max_length=80)
    item_url = StringType(required=False)
    image_url = StringType(required=False)
    subtitle = StringType(required=False, max_length=80)
    buttons = ListType(ModelType(PostbackButton), required=False, max_size=3)
<file_sep>from schematics.models import Model
from schematics.types import StringType
from schematics.types.compound import ModelType

from generic_payload import GenericPayload


class GenericAttachment(Model):
    type = StringType(required=True, choices=['template'],
                      default='template')
    payload = ModelType(GenericPayload, required=True)
<file_sep>from schematics.models import Model
from schematics.types import StringType


class QuickReply(Model):
    content_type = StringType(required=True, choices=['text', 'location'],
                              default='text')
    title = StringType(required=False, max_length=20)
    payload = StringType(max_length=1000)
    image_url = StringType(required=False)
<file_sep>REGISTRY = pasmod
SHELL = /bin/bash
TAG = 0.0.1
NAME = botics

.PHONY: test
# target: test – run project tests
test:
	docker run -it --rm=true --name=$(NAME) $(REGISTRY)/$(NAME) python -m pytest $(NAME)/test

.PHONY: help
# target: help – display all callable targets
help:
	@echo
	@egrep "^\s*#\s*target\s*:\s*" [Mm]akefile \
	| sed -r "s/^\s*#\s*target\s*:\s*//g"
	@echo

.PHONY: clean
# target: clean – clean the project's directrory
clean:
	@find . \
		-name *.py[cod] -exec rm -fv {} + -o \
		-name __pycache__ -exec rm -rfv {} +

.PHONY: build
# target: build – build the docker image
build:
	docker build --no-cache -t $(REGISTRY)/$(NAME) .
	docker tag $(REGISTRY)/$(NAME) $(REGISTRY)/$(NAME):$(TAG)

.PHONY: run
# target: run – run the docker container
run: stop
	docker run -it --rm=true -v $(shell pwd):/var/www --name=$(NAME) $(REGISTRY)/$(NAME) bash -l

.PHONY: stop
# target: stop – stop the docker container
stop:
	docker rm -f $(NAME) || true
<file_sep>from flask import Flask, request
import os

app = Flask(__name__)
VERIFY_TOKEN = os.environ.get('VERIFY_TOKEN', None)


@app.route('/webhook', methods=['GET'])
def verify():
    if request.args.get("hub.mode") == "subscribe" and \
            request.args.get("hub.challenge"):
        if not request.args.get("hub.verify_token") == VERIFY_TOKEN:
            return "Verification token mismatch", 403
        return request.args["hub.challenge"], 200

    return "OK!", 200


if __name__ == '__main__':
    app.run(debug=True)
<file_sep>import requests
from schematics.exceptions import ValidationError

from botics.models.generic_attachment import GenericAttachment
from botics.models.generic_payload import GenericPayload
from botics.models.recipient import Recipient
from botics.models.sender_action import SenderAction
from botics.models.text_message import TextMessage

API_URL = "https://graph.facebook.com/v2.6/me/messages"


class Client(object):
    def __init__(self, page_access_token=None):
        self.page_access_token = page_access_token

    def send_action(self, recipient_id=None, sender_action=None):
        sender_action = SenderAction({"sender_action": sender_action})
        recipient = Recipient({"id": recipient_id})
        sender_action.validate()
        content = {"recipient": recipient.to_primitive()}
        content.update(sender_action.to_primitive())
        params = {'access_token': self.page_access_token}
        response = requests.post(API_URL, params=params, json=content)
        return response.ok

    def send_text_message(self, recipient_id=None, text=None):
        text_message = TextMessage({"text": text})
        recipient = Recipient({"id": recipient_id})
        try:
            text_message.validate()
        except ValidationError, e:
            print(e.message)
        content = {"recipient": recipient.to_primitive()}
        content.update({'message': text_message.to_primitive()})
        params = {'access_token': self.page_access_token}
        response = requests.post(API_URL, params=params, json=content)
        return response.ok

    def send_generic_template(self, recipient_id, generic_elements):
        generic_payload = GenericPayload({"elements": generic_elements})
        generic_attachment = GenericAttachment({"payload": generic_payload})
        recipient = Recipient({"id": recipient_id})
        try:
            generic_payload.validate()
        except ValidationError, e:
            print(e.message)
        try:
            generic_attachment.validate()
        except ValidationError, e:
            print(e.message)
        content = {"recipient": recipient.to_primitive()}
        content.update({'message': {'attachment':
                                    generic_attachment.to_primitive()}})
        params = {'access_token': self.page_access_token}
        response = requests.post(API_URL, params=params, json=content)
        return response.ok

    def send_quick_reply_message(self, recipient_id, quick_reply_message):
        recipient = Recipient({"id": recipient_id})
        try:
            quick_reply_message.validate()
        except ValidationError, e:
            print(e.message)
        content = {"recipient": recipient.to_primitive()}
        content.update({'message': quick_reply_message.to_primitive()})
        params = {'access_token': self.page_access_token}
        response = requests.post(API_URL, params=params, json=content)
        return response.ok
<file_sep>from schematics.models import Model
from schematics.types import StringType


class TextMessage(Model):
    text = StringType(required=True)
<file_sep>from schematics.models import Model
from schematics.types import StringType, BooleanType


class URLButton(Model):
    type = StringType(required=True, choices=['web_url'], default='web_url')
    title = StringType(required=True, max_length=20)
    url = StringType(required=True)
    webview_height_ratio = StringType(required=False,
                                      choices=['compact', 'tall', 'full'],
                                      default='full')
    messenger_extensions = BooleanType(required=False)
    fallback_url = StringType(required=False)
<file_sep>from schematics.models import Model
from schematics.types import StringType
from schematics.types.compound import ListType, ModelType

from generic_element import GenericElement


class GenericPayload(Model):
    template_type = StringType(required=True, choices=['generic'],
                               default='generic')
    elements = ListType(ModelType(GenericElement), min_size=1, max_size=10)
<file_sep>FROM pasmod/miniconder2

WORKDIR /var/www
ADD . .

RUN pip install --upgrade pip
RUN pip install -r requirements.txt
RUN pip install -r requirements-test.txt
