Browse Source

Change sms management. Move it to views

devel
bashmak 8 years ago
parent
commit
3e638fe202
  1. 4
      abonapp/views.py
  2. 2
      devapp/views.py
  3. 96
      dialing.py
  4. 3
      dialing_app/urls.py
  5. 58
      dialing_app/views.py
  6. 9
      djing/__init__.py
  7. 4
      djing/global_base_views.py

4
abonapp/views.py

@ -28,7 +28,7 @@ from statistics.models import getModel
from group_app.models import Group from group_app.models import Group
from guardian.shortcuts import get_objects_for_user, assign_perm from guardian.shortcuts import get_objects_for_user, assign_perm
from guardian.decorators import permission_required_or_403 as permission_required from guardian.decorators import permission_required_or_403 as permission_required
from djing.global_base_views import OrderingMixin, BaseListWithFiltering, HashAuthView, AllowedSubnetMixin
from djing.global_base_views import OrderingMixin, BaseListWithFiltering, SecureApiView
PAGINATION_ITEMS_PER_PAGE = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10) PAGINATION_ITEMS_PER_PAGE = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
@ -1121,7 +1121,7 @@ def search_abon(request):
return results return results
class DhcpLever(AllowedSubnetMixin, HashAuthView):
class DhcpLever(SecureApiView):
# #
# Api view for dhcp event # Api view for dhcp event
# #

2
devapp/views.py

@ -514,7 +514,7 @@ def fix_port_conflict(request, group_id, device_id, port_id):
}) })
class OnDeviceMonitoringEvent(global_base_views.AllowedSubnetMixin, global_base_views.HashAuthView):
class OnDeviceMonitoringEvent(global_base_views.SecureApiView):
# #
# Api view for monitoring devices # Api view for monitoring devices
# #

96
dialing.py

@ -1,26 +1,53 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os, signal
from pid.decorator import pidfile
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings")
django.setup()
from messaging.sms import SmsSubmit, SmsDeliver
from typing import Dict, Optional, AnyStr
import re import re
import asterisk.manager
import signal
from time import sleep from time import sleep
from dialing_app.models import SMSModel, SMSOut
from django.conf import settings
from urllib.parse import urlencode
from urllib.request import urlopen
from urllib.error import HTTPError
from hashlib import sha256
from pid.decorator import pidfile
from messaging.sms import SmsSubmit, SmsDeliver
from asterisk import manager as ast_mngr
ASTERISK_MANAGER_AUTH = getattr(settings, 'ASTERISK_MANAGER_AUTH', {
ASTERISK_MANAGER_AUTH = {
'username': 'admin', 'username': 'admin',
'password': 'admin',
'password': 'password',
'host': '127.0.0.1' 'host': '127.0.0.1'
})
}
API_AUTH_SECRET = 'your api secret'
SERVER_DOMAIN = 'http://localhost:8000'
outbox_messages = False outbox_messages = False
def calc_hash(data):
if type(data) is str:
result_data = data.encode('utf-8')
else:
result_data = bytes(data)
return sha256(result_data).hexdigest()
def secure_request(data: Dict) -> Optional[AnyStr]:
vars_to_hash = [str(v) for v in data.values()]
vars_to_hash.sort()
vars_to_hash.append(API_AUTH_SECRET)
sign = calc_hash('_'.join(vars_to_hash))
data.update({'sign': sign})
try:
with urlopen("%s/dialing/api/sms?%s" % (SERVER_DOMAIN, urlencode(data))) as r:
return r.read()
except ConnectionRefusedError:
print('ERROR: connection refused')
except HTTPError as e:
print('ERROR:', e)
class SMS(object): class SMS(object):
def __init__(self, text, who, dev): def __init__(self, text, who, dev):
self.text = text self.text = text
@ -45,7 +72,7 @@ class ChunkedMsg(object):
self.sms = sms self.sms = sms
class MyAstManager(asterisk.manager.Manager):
class MyAstManager(ast_mngr.Manager):
sms_chunks = list() sms_chunks = list()
def new_chunked_sms(self, count, ref, sms): def new_chunked_sms(self, count, ref, sms):
@ -57,11 +84,14 @@ class MyAstManager(asterisk.manager.Manager):
print('Inbox %s:' % sms.who, sms.text) print('Inbox %s:' % sms.who, sms.text)
if not isinstance(sms, SMS): if not isinstance(sms, SMS):
raise TypeError raise TypeError
SMSModel.objects.create(
who=sms.who,
dev=sms.dev,
text=sms.text
)
response = secure_request({
'who': sms.who,
'dev': sms.dev,
'text': sms.text,
'cmd': 'save_sms'
})
if response is not None:
print(response)
def send_sms(self, dev, recipient, utext): def send_sms(self, dev, recipient, utext):
if not validate_tel(recipient): if not validate_tel(recipient):
@ -88,13 +118,19 @@ class MyAstManager(asterisk.manager.Manager):
self.new_chunked_sms(cnt, ref, sms) self.new_chunked_sms(cnt, ref, sms)
def send_from_outbox(self): def send_from_outbox(self):
messages = SMSOut.objects.filter(status='nw')
messages = secure_request({'cmd': 'get_new'})
for msg in messages: for msg in messages:
if self.send_sms(dev='sim_8318999', recipient=msg.dst, utext=msg.text): if self.send_sms(dev='sim_8318999', recipient=msg.dst, utext=msg.text):
msg.status = 'st'
msg_status = 'st'
else: else:
msg.status = 'fd'
msg.save(update_fields=['status'])
msg_status = 'fd'
result = secure_request({
'cmd': 'update_status',
'mid': msg.pk,
'status': msg_status
})
if result is not None:
print(result)
manager = MyAstManager() manager = MyAstManager()
@ -104,10 +140,10 @@ def validate_tel(tel, reg=re.compile(r'^\+7978\d{7}$')):
return bool(re.match(reg, tel)) return bool(re.match(reg, tel))
def handle_shutdown(event, manager):
print("Recieved shutdown event")
manager.close()
# we could analize the event and reconnect here
def handle_shutdown(event, mngr):
print("Received shutdown event")
mngr.close()
# we could analyze the event and reconnect here
def signal_handler(signum, frame): def signal_handler(signum, frame):
@ -159,11 +195,11 @@ def main():
manager.send_from_outbox() manager.send_from_outbox()
sleep(5) sleep(5)
except asterisk.manager.ManagerSocketException as e:
except ast_mngr.ManagerSocketException as e:
print("Error connecting to the manager: ", e) print("Error connecting to the manager: ", e)
except asterisk.manager.ManagerAuthException as e:
except ast_mngr.ManagerAuthException as e:
print("Error logging in to the manager: ", e) print("Error logging in to the manager: ", e)
except asterisk.manager.ManagerException as e:
except ast_mngr.ManagerException as e:
print("Error: ", e) print("Error: ", e)
finally: finally:
manager.logoff() manager.logoff()

3
dialing_app/urls.py

@ -10,5 +10,6 @@ urlpatterns = [
url(r'^requests$', views.VoiceMailRequestsListView.as_view(), name='vmail_request'), url(r'^requests$', views.VoiceMailRequestsListView.as_view(), name='vmail_request'),
url(r'^reports$', views.VoiceMailReportsListView.as_view(), name='vmail_report'), url(r'^reports$', views.VoiceMailReportsListView.as_view(), name='vmail_report'),
url(r'^sms/in$', views.InboxSMSListView.as_view(), name='inbox_sms'), url(r'^sms/in$', views.InboxSMSListView.as_view(), name='inbox_sms'),
url(r'^sms/send$', views.send_sms, name='send_sms')
url(r'^sms/send$', views.send_sms, name='send_sms'),
url(r'^api/sms$', views.SmsManager.as_view())
] ]

58
dialing_app/views.py

@ -11,10 +11,13 @@ from django.views.generic import ListView
from guardian.decorators import permission_required_or_403 as permission_required from guardian.decorators import permission_required_or_403 as permission_required
from django.db.models import Q from django.db.models import Q
from django.conf import settings from django.conf import settings
from jsonview.decorators import json_view
from abonapp.models import Abon from abonapp.models import Abon
from mydefs import only_admins
from .models import AsteriskCDR, SMSModel
from djing.global_base_views import SecureApiView
from djing import JSONType
from mydefs import only_admins, safe_int
from .models import AsteriskCDR, SMSModel, SMSOut
from .forms import SMSOutForm from .forms import SMSOutForm
@ -151,3 +154,54 @@ def send_sms(request):
'form': frm, 'form': frm,
'path': path 'path': path
}, request=request) }, request=request)
class SmsManager(SecureApiView):
#
# Api view for management sms from dongle
#
http_method_names = ['get']
@staticmethod
def bad_cmd(**kwargs) -> JSONType:
return {'text': 'Command is not allowed'}
@method_decorator(json_view)
def get(self, request, *args, **kwargs):
cmd = request.GET.get('cmd')
data = request.GET.dict()
handler = getattr(self, cmd.lower(), self.bad_cmd)
del data['cmd']
del data['sign']
return handler(**data)
@staticmethod
def save_sms(**kwargs) -> JSONType:
sms = SMSModel.objects.create(
who=kwargs.get('who'),
dev=kwargs.get('dev'),
text=kwargs.get('text')
)
return {'status': 'ok', 'sms_id': sms.pk}
@staticmethod
def update_status(**kwargs) -> JSONType:
msg_id = safe_int(kwargs.get('mid'))
if msg_id != 0:
status = kwargs.get('status')
update_count = SMSOut.objects.filter(pk=msg_id).update(status=status)
return {
'text': 'Status updated',
'update_count': update_count
}
return {'text': 'Bad mid parameter'}
@staticmethod
def get_new(**kwargs) -> JSONType:
msgs = SMSOut.objects.filter(status='nw').defer('status')
res = [{
'when': round(m.timestamp),
'dst': m.dst,
'text': m.text
} for m in msgs]
return res

9
djing/__init__.py

@ -1,6 +1,7 @@
import os import os
import re import re
import importlib import importlib
import typing as t
from django.shortcuts import _get_queryset from django.shortcuts import _get_queryset
from netaddr import mac_unix, mac_eui48 from netaddr import mac_unix, mac_eui48
@ -67,3 +68,11 @@ def get_object_or_None(klass, *args, **kwargs):
) )
except queryset.model.DoesNotExist: except queryset.model.DoesNotExist:
return return
# Type for all objects who can convertable to json
_JSONType_0 = t.Union[str, int, float, bool, None, t.Dict[str, t.Any], t.List[t.Any]]
_JSONType_1 = t.Union[str, int, float, bool, None, t.Dict[str, _JSONType_0], t.List[_JSONType_0]]
_JSONType_2 = t.Union[str, int, float, bool, None, t.Dict[str, _JSONType_1], t.List[_JSONType_1]]
_JSONType_3 = t.Union[str, int, float, bool, None, t.Dict[str, _JSONType_2], t.List[_JSONType_2]]
JSONType = t.Union[str, int, float, bool, None, t.Dict[str, _JSONType_3], t.List[_JSONType_3]]

4
djing/global_base_views.py

@ -92,6 +92,10 @@ class AllowedSubnetMixin(object):
return HttpResponseForbidden('Access Denied') return HttpResponseForbidden('Access Denied')
class SecureApiView(AllowedSubnetMixin, HashAuthView):
pass
class OrderingMixin(object): class OrderingMixin(object):
""" """
Ordering result object list by @order_by variable in get request. Ordering result object list by @order_by variable in get request.

Loading…
Cancel
Save