Implement base SMS provider

PlaySMS integration
This commit is contained in:
Kumi 2020-04-13 12:08:59 +02:00
parent e288b44929
commit 9798849aab
19 changed files with 183 additions and 23 deletions

33
core/classes/sms.py Normal file
View file

@ -0,0 +1,33 @@
from typing import Union
class SMSNotSent(Exception):
'''SMS providers must raise SMSNotSent if an SMS was reported as not sent by the gateway.'''
class BaseSMSProvider:
'''SMS providers must be subclasses of BaseSMSProvider and implement at least is_active and sendSMS().'''
@property
def get_name(self):
return "Base SMS Provider"
@property
def get_logo(self):
return ""
@property
def is_active(self):
'''Returns True if the provider is properly configured and ready to use.'''
raise NotImplementedError(f"{type(self)} does not implement is_active!")
@property
def get_edit_url(self):
return
def sendSMS(self, recipients: Union[str, list], message: str):
'''Send an SMS message to one or more recipients
:param recipients: Recipient phone number as a string, or a list of multiple phone number strings
:param message: Message to be sent as a string
'''
raise NotImplementedError(f"{type(self)} does not implement sendSMS()!")

0
core/helpers/__init__.py Normal file
View file

5
core/helpers/files.py Normal file
View file

@ -0,0 +1,5 @@
import uuid
import os.path
def generate_storage_filename():
return uuid.uuid4()

View file

@ -1,4 +0,0 @@
from django.db import models
# Create your models here.

1
core/models/__init__.py Normal file
View file

@ -0,0 +1 @@
from core.models.files import *

13
core/models/files.py Normal file
View file

@ -0,0 +1,13 @@
from django.db.models import Model, CharField, ImageField, FileField
from core.helpers.files import generate_storage_filename
# Create your models here.
class ImageFile(Model):
filename = CharField(max_length=255)
file = ImageField(upload_to=generate_storage_filename)
class File(Model):
filename = CharField(max_length=255)
file = FileField(upload_to=generate_storage_filename)

39
core/modules/sms.py Normal file
View file

@ -0,0 +1,39 @@
import importlib
from django.conf import settings
from core.classes.navigation import NavItem, NavSection, Navigation
from dbsettings import getValue
providers = []
modules_available = []
for module in settings.EXPEPHALON_MODULES:
try:
mos = importlib.import_module(f"{module}.sms")
for provider in mos.SMSPROVIDERS:
providers.append(provider)
if mos.CREATE:
modules_available = mos.CREATE
except (AttributeError, ModuleNotFoundError):
continue
def get_sms_provider_by_name(name):
for provider in providers:
if provider.name == name:
return provider
def get_default_sms_provider_name():
return getValue("core.sms.default", False)
def get_default_sms_provider():
name = get_default_sms_provider_name()
if name:
for provider in providers:
if provider.name == name and provider.is_active:
return provider
for provider in providers:
if provider.is_active:
return provider

18
core/modules/urls.py Normal file
View file

@ -0,0 +1,18 @@
import importlib
from django.conf import settings
from django.urls import path
URLPATTERNS = []
for module in settings.EXPEPHALON_MODULES:
try:
mou = importlib.import_module(f"{module}.urls")
for url, action, name in mou.ADMIN_URLS:
URLPATTERNS.append(path(f'admin/modules/{module}/{url}', action, name=f"{module}_{name}"))
except (AttributeError, ModuleNotFoundError):
pass
if "dbsettings" in settings.INSTALLED_APPS:
from core.views import DBSettingsListView
URLPATTERNS.append(path("admin/dbsettings/", DBSettingsListView.as_view(), name="dbsettings"))

View file

@ -1,25 +1,10 @@
from django.contrib import admin
from django.urls import path, include from django.urls import path, include
from django.conf import settings
from core.views import DashboardView from core.views import DashboardView
from core.navigation import Navigation from core.modules.urls import URLPATTERNS
import importlib import importlib
urlpatterns = [ urlpatterns = [
path('admin/', DashboardView.as_view(), name="backend"), path('admin/', DashboardView.as_view(), name="backend"),
] ] + URLPATTERNS
for module in settings.EXPEPHALON_MODULES:
try:
mou = importlib.import_module(f"{module}.urls")
for url, action, name in mou.ADMIN_URLS:
urlpatterns.append(path(f'admin/modules/{module}/{url}', action, name=f"{module}_{name}"))
except (AttributeError, ModuleNotFoundError):
pass
if "dbsettings" in settings.INSTALLED_APPS:
from core.views import DBSettingsListView
urlpatterns.append(path("admin/dbsettings/", DBSettingsListView.as_view(), name="dbsettings"))

@ -1 +1 @@
Subproject commit a1bf7c0dbd874e1ebb941b545eb8e0fd00dd776a Subproject commit 06e4fcd801e3961de05f98bc5bf88a5a6a334408

View file

@ -1,5 +1,5 @@
from core.views import DashboardView from core.views import DashboardView
ADMIN_URLS = [ ADMIN_URLS = [
("", DashboardView.as_view(), "backend"), ("", DashboardView.as_view(), "demomodule_backend"),
] ]

4
module_dependencies.md Normal file
View file

@ -0,0 +1,4 @@
### playsms
* core

0
playsms/__init__.py Normal file
View file

5
playsms/apps.py Normal file
View file

@ -0,0 +1,5 @@
from django.apps import AppConfig
class PlaysmsConfig(AppConfig):
name = 'playsms'

55
playsms/models.py Normal file
View file

@ -0,0 +1,55 @@
from django.db.models import Model, CharField, BooleanField
from core.classes.sms import BaseSMSProvider, SMSNotSent
from urllib.parse import quote_plus
from urllib.request import urlopen
from typing import Union
import json
# Create your models here.
class PlaySMSServer(Model, BaseSMSProvider):
name = CharField(max_length=255)
logo = CharField(max_length=255)
https = BooleanField(default=True)
host = CharField(max_length=255)
username = CharField(max_length=255)
token = CharField(max_length=255)
@property
def is_active(self):
return True
@staticmethod
def getError(status):
if status["error_message"]:
return status["error_message"]
try:
if status["data"]["error"]:
return status["data"]["error"]
finally:
return
def sendSMS(self, recipients: Union[str, list], message: str):
'''Send an SMS message to one or more recipients
:param recipients: Recipient phone number as a string, or a list of multiple phone number strings
:param message: Message to be sent as a string
'''
if isinstance(recipients, list):
recipients = ",".join(recipients)
url = 'http%s://%s/index.php?app=ws&u="%s"&h="%s"&op=pv&to=%s&msg=%s' % ("s" if self.https else "", self.host, self.username, self.token, recipients, quote_plus(message))
response = urlopen(url)
status = json.loads(response.read().decode())
error = PlaySMSServer.getError(status)
if error:
raise SMSNotSent(f'An error occurred trying to send the SMS: {error}')

0
playsms/sms.py Normal file
View file

2
playsms/urls.py Normal file
View file

@ -0,0 +1,2 @@
ADMIN_URLS = [
]

3
playsms/views.py Normal file
View file

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

View file

@ -2,3 +2,4 @@ django[argon2]
mysqlclient mysqlclient
django-storages django-storages
boto3 boto3
Pillow