Skip to content

Commit

Permalink
Merge pull request #8 from jlmadurga/feature/api
Browse files Browse the repository at this point in the history
Feature/api
  • Loading branch information
jlmadurga committed Mar 14, 2016
2 parents d609ffb + 6ee9f26 commit b8815d8
Show file tree
Hide file tree
Showing 11 changed files with 728 additions and 27 deletions.
32 changes: 32 additions & 0 deletions microbot/migrations/0004_auto_20160311_1039.py
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
from django.conf import settings


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('microbot', '0003_auto_20160310_0941'),
]

operations = [
migrations.AddField(
model_name='bot',
name='owner',
field=models.ForeignKey(related_name='bots', default=None, to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
migrations.AlterField(
model_name='headerparam',
name='request',
field=models.ForeignKey(related_name='header_parameters', verbose_name='Request', to='microbot.Request'),
),
migrations.AlterField(
model_name='urlparam',
name='request',
field=models.ForeignKey(related_name='url_parameters', verbose_name='Request', to='microbot.Request'),
),
]
2 changes: 2 additions & 0 deletions microbot/models/bot.py
Expand Up @@ -12,12 +12,14 @@
from django.core.urlresolvers import Resolver404
from telegram import ParseMode, ReplyKeyboardHide, ReplyKeyboardMarkup
import ast
from django.conf import settings

logger = logging.getLogger(__name__)


@python_2_unicode_compatible
class Bot(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='bots')
token = models.CharField(_('Token'), max_length=100, db_index=True)
user_api = models.OneToOneField(User, verbose_name=_("Bot User"), related_name='bot',
on_delete=models.CASCADE, blank=True, null=True)
Expand Down
88 changes: 86 additions & 2 deletions microbot/serializers.py
@@ -1,8 +1,9 @@
from rest_framework import serializers
from microbot.models import User, Chat, Message, Update
from microbot.models import User, Chat, Message, Update, Bot, EnvironmentVar, Handler, Request, UrlParam, HeaderParam
from datetime import datetime
import time


class UserSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.IntegerField()

Expand Down Expand Up @@ -63,4 +64,87 @@ def create(self, validated_data):
update, _ = Update.objects.get_or_create(update_id=validated_data['update_id'],
message=message)

return update
return update

class UserAPISerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('first_name', 'last_name', 'username')

class BotSerializer(serializers.ModelSerializer):
info = UserAPISerializer(many=False, source='user_api', read_only=True)

class Meta:
model = Bot
fields = ('token', 'created', 'enabled', 'info')
read_only_fields = ('created', 'info')

class EnvironmentVarSerializer(serializers.ModelSerializer):
class Meta:
model = EnvironmentVar
fields = ('key', 'value')

class AbsParamSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = UrlParam
fields = ('key', 'value_template')

class RequestSerializer(serializers.HyperlinkedModelSerializer):
url_parameters = AbsParamSerializer(many=True)
header_parameters = AbsParamSerializer(many=True)
class Meta:
model = Request
fields = ('url_template', 'method', 'data', 'url_parameters', 'header_parameters')

class HandlerSerializer(serializers.ModelSerializer):
request = RequestSerializer(many=False)
class Meta:
model = Handler
fields = ('pattern', 'response_text_template', 'response_keyboard_template', 'enabled', 'request')

def _create_params(self, params, model, request):
for param in params:
model.objects.get_or_create(key=param['key'],
value_template=param['value_template'],
request=request)

def _update_params(self, params, query_get):
for param in params:
instance_param = query_get(key=param['key'])
instance_param.key = param['key']
instance_param.value_template = param['value_template']
instance_param.save()

def create(self, validated_data):
request, _ = Request.objects.get_or_create(**validated_data['request'])

handler, _ = Handler.objects.get_or_create(pattern=validated_data['pattern'],
response_text_template=validated_data['response_text_template'],
response_keyboard_template=validated_data['response_keyboard_template'],
enabled=validated_data['enabled'],
request=request)

self._create_params(validated_data['request']['url_parameters'], UrlParam, request)
self._create_params(validated_data['request']['header_parameters'], HeaderParam, request)


return handler

def update(self, instance, validated_data):
instance.pattern = validated_data.get('pattern', instance.pattern)
instance.response_text_template = validated_data.get('response_text_template', instance.response_text_template)
instance.response_keyboard_template = validated_data.get('response_keyboard_template', instance.response_keyboard_template)
instance.enabled = validated_data.get('enabled', instance.enabled)

instance.request.url_template = validated_data['request'].get('url_template', instance.request.url_template)
instance.request.method = validated_data['request'].get('method', instance.request.method)
instance.request.data = validated_data['request'].get('data', instance.request.data)
instance.request.save()

self._update_params(validated_data['request']['url_parameters'], instance.request.url_parameters.get)
self._update_params(validated_data['request']['header_parameters'], instance.request.header_parameters.get)

instance.save()
return instance


3 changes: 2 additions & 1 deletion microbot/test/factories/__init__.py
@@ -1,4 +1,5 @@
from microbot.test.factories.user import UserFactory # noqa
from microbot.test.factories.bot import BotFactory # noqa
from microbot.test.factories.telegram_lib import (UserLibFactory, ChatLibFactory, # noqa
MessageLibFactory, UpdateLibFactory) # noqa
from microbot.test.factories.handler import HandlerFactory, RequestFactory, UrlParamFactory, HeaderParamFactory # noqa
from microbot.test.factories.handler import HandlerFactory, RequestFactory, UrlParamFactory, HeaderParamFactory # noqa
7 changes: 4 additions & 3 deletions microbot/test/factories/bot.py
@@ -1,9 +1,10 @@
# coding=utf-8
from factory import DjangoModelFactory
from factory import DjangoModelFactory, SubFactory
from microbot.models import Bot

from microbot.test.factories import UserFactory

class BotFactory(DjangoModelFactory):
class Meta:
model = Bot
token = "204840063:AAGKVVNf0HUTFoQKcgmLrvPv4tyP8xRCkFc"
token = "204840063:AAGKVVNf0HUTFoQKcgmLrvPv4tyP8xRCkFc"
owner = SubFactory(UserFactory)
15 changes: 15 additions & 0 deletions microbot/test/factories/user.py
@@ -0,0 +1,15 @@
# coding=utf-8
from factory import DjangoModelFactory, Sequence, PostGenerationMethodCall
from django.conf import settings

class UserFactory(DjangoModelFactory):
class Meta:
model = settings.AUTH_USER_MODEL

email = Sequence(lambda n: 'user%d@test.com' % n)
username = Sequence(lambda n: 'user%d' % n)
password = PostGenerationMethodCall('set_password', 'adm1n')

is_superuser = False
is_staff = False
is_active = True
6 changes: 6 additions & 0 deletions microbot/urls.py
Expand Up @@ -4,4 +4,10 @@

urlpatterns = [
url(r'^telegrambot/(?P<token>[-_:a-zA-Z0-9]+)/$', csrf_exempt(views.WebhookView.as_view()), name='telegrambot'),
url(r'^api/bots/$', views.BotList.as_view(), name='bot-list'),
url(r'^api/bots/(?P<pk>[0-9]+)/$', views.BotDetail.as_view(), name='bot-detail'),
url(r'^api/bots/(?P<bot_pk>[0-9]+)/env/$', views.EnvironmentVarList.as_view(), name='env-list'),
url(r'^api/bots/(?P<bot_pk>[0-9]+)/env/(?P<pk>[0-9]+)/$', views.EnvironmentVarDetail.as_view(), name='env-list'),
url(r'^api/bots/(?P<bot_pk>[0-9]+)/handlers/$', views.HandlerList.as_view(), name='handler-list'),
url(r'^api/bots/(?P<bot_pk>[0-9]+)/handlers/(?P<pk>[0-9]+)/$', views.HandlerDetail.as_view(), name='handler-detail'),
]
156 changes: 153 additions & 3 deletions microbot/views.py
@@ -1,13 +1,18 @@
from rest_framework.views import APIView
from microbot.serializers import UpdateSerializer
from microbot.models import Bot
from microbot.serializers import UpdateSerializer, BotSerializer, EnvironmentVarSerializer,\
HandlerSerializer
from microbot.models import Bot, EnvironmentVar, Handler, Request
from rest_framework.response import Response
from rest_framework import status
from telegram import Update
import logging
import sys
import traceback
from microbot.tasks import handle_update
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication
from django.http.response import Http404
from rest_framework import exceptions

logger = logging.getLogger(__name__)

Expand All @@ -32,4 +37,149 @@ def post(self, request, token):
else:
return Response(serializer.data, status=status.HTTP_200_OK)
logger.error("Validation error: %s from message %s" % (serializer.errors, request.data))
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class MicrobotAPIView(APIView):
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,)

def get_bot(self, pk, user):
try:
bot = Bot.objects.get(pk=pk)
if bot.owner != user:
raise exceptions.AuthenticationFailed()
return bot
except Bot.DoesNotExist:
raise Http404

class BotList(MicrobotAPIView):

def get(self, request, format=None):
bots = Bot.objects.filter(owner=request.user)
serializer = BotSerializer(bots, many=True)
return Response(serializer.data)

def post(self, request, format=None):
serializer = BotSerializer(data=request.data)
if serializer.is_valid():
Bot.objects.create(owner=request.user,
token=serializer.data['token'],
enabled=serializer.data['enabled'])
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class BotDetail(MicrobotAPIView):

def get(self, request, pk, format=None):
bot = self.get_bot(pk, request.user)
serializer = BotSerializer(bot)
return Response(serializer.data)

def put(self, request, pk, format=None):
bot = self.get_bot(pk, request.user)
serializer = BotSerializer(bot, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

def delete(self, request, pk, format=None):
bot = self.get_bot(pk, request.user)
bot.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

class ListBotAPIView(MicrobotAPIView):
serializer = None

def _query(self, bot):
raise NotImplemented

def _creator(self, bot, serializer):
raise NotImplemented

def get(self, request, bot_pk, format=None):
bot = self.get_bot(bot_pk, request.user)
serializer = self.serializer(self._query(bot), many=True)
return Response(serializer.data)

def post(self, request, bot_pk, format=None):
bot = self.get_bot(bot_pk, request.user)
serializer = self.serializer(data=request.data)
if serializer.is_valid():
self._creator(bot, serializer)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class DetailBotAPIView(MicrobotAPIView):
model = None
serializer = None

def _user(self, obj):
return obj.bot.owner

def get_object(self, pk, bot, user):
try:
obj = self.model.objects.get(pk=pk, bot=bot)
if self._user(obj) != user:
raise exceptions.AuthenticationFailed()
return obj
except self.model.DoesNotExist:
raise Http404

def get(self, request, bot_pk, pk, format=None):
bot = self.get_bot(bot_pk, request.user)
obj = self.get_object(pk, bot, request.user)
serializer = self.serializer(obj)
return Response(serializer.data)

def put(self, request, bot_pk, pk, format=None):
bot = self.get_bot(bot_pk, request.user)
obj = self.get_object(pk, bot, request.user)
serializer = self.serializer(obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

def delete(self, request, bot_pk, pk, format=None):
bot = self.get_bot(bot_pk, request.user)
obj = self.get_object(pk, bot, request.user)
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)


class EnvironmentVarList(ListBotAPIView):
serializer = EnvironmentVarSerializer

def _query(self, bot):
return bot.env_vars.all()

def _creator(self, bot, serializer):
EnvironmentVar.objects.create(bot=bot,
key=serializer.data['key'],
value=serializer.data['value'])

class EnvironmentVarDetail(DetailBotAPIView):
model = EnvironmentVar
serializer = EnvironmentVarSerializer


class HandlerList(ListBotAPIView):
serializer = HandlerSerializer

def _query(self, bot):
return bot.handlers.all()

def _creator(self, bot, serializer):
request = Request.objects.create(url_template=serializer.data['request']['url_template'],
method=serializer.data['request']['method'])
Handler.objects.create(bot=bot,
pattern=serializer.data['pattern'],
response_text_template=serializer.data['response_text_template'],
response_keyboard_template=serializer.data['response_keyboard_template'],
enabled=serializer.data['enabled'],
request=request)

class HandlerDetail(DetailBotAPIView):
model = Handler
serializer = HandlerSerializer

0 comments on commit b8815d8

Please sign in to comment.