Compare commits
No commits in common. "master" and "v3.6.4" have entirely different histories.
|
@ -3,7 +3,3 @@ RewriteRule ^assets - [L]
|
||||||
RewriteRule ^.well-known - [L]
|
RewriteRule ^.well-known - [L]
|
||||||
RewriteRule ^data/public/ - [L]
|
RewriteRule ^data/public/ - [L]
|
||||||
RewriteRule . index.php
|
RewriteRule . index.php
|
||||||
|
|
||||||
<IfModule headers_module>
|
|
||||||
Header always set Content-Security-Policy "upgrade-insecure-requests;"
|
|
||||||
</ifModule>
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ interface AdapterInterface
|
||||||
* ]
|
* ]
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
public static function inbound_call_callback(): array;
|
public function inbound_call_callback(): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called on reception of a end call notification.
|
* Method called on reception of a end call notification.
|
||||||
|
@ -221,5 +221,5 @@ interface AdapterInterface
|
||||||
* ]
|
* ]
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
public static function end_call_callback(): array;
|
public function end_call_callback(): array;
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,12 +259,12 @@ namespace adapters;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,7 +280,6 @@ namespace adapters;
|
||||||
$command_parts = [
|
$command_parts = [
|
||||||
PWD . '/bin/gammu_get_unread_sms.py',
|
PWD . '/bin/gammu_get_unread_sms.py',
|
||||||
escapeshellarg($this->data['config_file']),
|
escapeshellarg($this->data['config_file']),
|
||||||
'--delete'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$return = $this->exec_command($command_parts);
|
$return = $this->exec_command($command_parts);
|
||||||
|
@ -336,12 +335,12 @@ namespace adapters;
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -508,12 +508,12 @@ class KannelAdapter implements AdapterInterface
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -486,12 +486,12 @@ class OctopushShortcodeAdapter implements AdapterInterface
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -479,12 +479,12 @@ class OctopushVirtualNumberAdapter implements AdapterInterface
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -499,12 +499,12 @@ class OdysseyMessagingAdapter implements AdapterInterface
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,12 +406,12 @@ namespace adapters;
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -396,12 +396,12 @@ namespace adapters;
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -351,7 +351,7 @@ namespace adapters;
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
$response = [
|
$response = [
|
||||||
'error' => false,
|
'error' => false,
|
||||||
|
@ -380,7 +380,7 @@ namespace adapters;
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
$response = [
|
$response = [
|
||||||
'error' => false,
|
'error' => false,
|
||||||
|
|
|
@ -374,12 +374,12 @@ class TwilioVirtualNumberAdapter implements AdapterInterface
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function inbound_call_callback(): array
|
public function inbound_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function end_call_callback(): array
|
public function end_call_callback(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,236 +1,56 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: UTF-8 -*-
|
# -*- coding: UTF-8 -*-
|
||||||
# vim: expandtab sw=4 ts=4 sts=4:
|
# vim: expandtab sw=4 ts=4 sts=4:
|
||||||
|
#
|
||||||
# (C) 2003 - 2018 Michal Čihař <michal@cihar.com> - python-gammu
|
|
||||||
# (C) 2015 - 2021 Raspian France <raspbianfrance@gmail.com> - RaspianFrance/raspisms
|
|
||||||
# (C) 2022 - Orsiris de Jong <orsiris.dejong@netperfect.fr> - NetInvent SASU
|
|
||||||
|
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
|
||||||
__intname__ = "gammu_get_unread_sms.py"
|
|
||||||
__author__ = "Orsiris de Jong - <orsiris.dejong@netperfect.fr>"
|
|
||||||
__version__ = "2.0.2"
|
|
||||||
__build__ = "2022102501"
|
|
||||||
__compat__ = "python2.7+"
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import gammu
|
import gammu
|
||||||
|
import sys
|
||||||
import json
|
import json
|
||||||
import logging
|
|
||||||
from logging.handlers import RotatingFileHandler
|
|
||||||
import tempfile
|
|
||||||
from argparse import ArgumentParser
|
|
||||||
import subprocess
|
|
||||||
import re
|
|
||||||
|
|
||||||
LOG_FILE = "/var/log/{}.log".format(__intname__)
|
def main():
|
||||||
_DEBUG = os.environ.get("_DEBUG", False)
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def get_logger(log_file):
|
|
||||||
# We would normally use ofunctions.logger_utils here with logger_get_logger(), but let's keep no dependencies
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
filehandler = RotatingFileHandler(
|
|
||||||
log_file, mode="a", encoding="utf-8", maxBytes=1048576, backupCount=3
|
|
||||||
)
|
|
||||||
except OSError:
|
|
||||||
try:
|
|
||||||
temp_log_file = tempfile.gettempdir() + os.sep + __name__ + ".log"
|
|
||||||
filehandler = RotatingFileHandler(
|
|
||||||
temp_log_file,
|
|
||||||
mode="a",
|
|
||||||
encoding="utf-8",
|
|
||||||
maxBytes=1048576,
|
|
||||||
backupCount=3,
|
|
||||||
)
|
|
||||||
except OSError as exc:
|
|
||||||
print("Cannot create log file: %s" % exc.__str__())
|
|
||||||
filehandler = None
|
|
||||||
|
|
||||||
_logger = logging.getLogger()
|
|
||||||
if _DEBUG:
|
|
||||||
_logger.setLevel(logging.DEBUG)
|
|
||||||
else:
|
|
||||||
_logger.setLevel(logging.INFO)
|
|
||||||
|
|
||||||
formatter = logging.Formatter("%(asctime)s :: %(levelname)s :: %(message)s")
|
|
||||||
if filehandler:
|
|
||||||
filehandler.setFormatter(formatter)
|
|
||||||
_logger.addHandler(filehandler)
|
|
||||||
consolehandler = logging.StreamHandler()
|
|
||||||
consolehandler.setFormatter(formatter)
|
|
||||||
_logger.addHandler(consolehandler)
|
|
||||||
return _logger
|
|
||||||
except Exception as exc:
|
|
||||||
print("Cannot create logger instance: %s" % exc.__str__())
|
|
||||||
|
|
||||||
|
|
||||||
def get_gammu_version():
|
|
||||||
# Quite badly coded, i'd use command_runner but I try to not have dependencies here
|
|
||||||
try:
|
|
||||||
proc = subprocess.Popen(
|
|
||||||
["LC_ALL=C gammu", "--version"], shell=True, stdout=subprocess.PIPE
|
|
||||||
)
|
|
||||||
stdout, _ = proc.communicate()
|
|
||||||
version = re.search(r"Gammu version ([0-9]+)\.([0-9]+)\.([0-9]+)", str(stdout))
|
|
||||||
# dont' bother to return version[0] since it's the whole match
|
|
||||||
return (int(version[1]), int(version[2]), int(version[3]))
|
|
||||||
except Exception as exc:
|
|
||||||
logger.error("Cannot get gammu version: %s" % exc.__str__())
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_gammu_handle(config_file):
|
|
||||||
state_machine = gammu.StateMachine()
|
state_machine = gammu.StateMachine()
|
||||||
|
|
||||||
if config_file:
|
if len(sys.argv) < 2:
|
||||||
state_machine.ReadConfig(Filename=config_file)
|
sys.exit(1)
|
||||||
else:
|
else :
|
||||||
state_machine.Readconfig()
|
state_machine.ReadConfig(Filename=sys.argv[1])
|
||||||
|
del sys.argv[1]
|
||||||
|
|
||||||
state_machine.Init()
|
state_machine.Init()
|
||||||
|
|
||||||
return state_machine
|
|
||||||
|
|
||||||
|
|
||||||
def load_sms_from_gammu(state_machine):
|
|
||||||
"""
|
|
||||||
The actual function that retrieves SMS via GAMMU from your modem / phone
|
|
||||||
Also concatenates multiple SMS into single long SMS
|
|
||||||
"""
|
|
||||||
status = state_machine.GetSMSStatus()
|
status = state_machine.GetSMSStatus()
|
||||||
|
|
||||||
remaining_sms = status["SIMUsed"] + status["PhoneUsed"] + status["TemplatesUsed"]
|
remain = status['SIMUsed'] + status['PhoneUsed'] + status['TemplatesUsed']
|
||||||
logger.debug("Found %s sms" % remaining_sms)
|
|
||||||
sms_list = []
|
start = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
is_first_message = True
|
while remain > 0:
|
||||||
while remaining_sms > 0:
|
if start:
|
||||||
if is_first_message:
|
sms = state_machine.GetNextSMS(Start=True, Folder=0)
|
||||||
sms = state_machine.GetNextSMS(Start=is_first_message, Folder=0)
|
start = False
|
||||||
is_first_message = False
|
|
||||||
else:
|
else:
|
||||||
sms = state_machine.GetNextSMS(Location=sms[0]["Location"], Folder=0)
|
sms = state_machine.GetNextSMS(
|
||||||
remaining_sms = remaining_sms - len(sms)
|
Location=sms[0]['Location'], Folder=0
|
||||||
sms_list.append(sms)
|
)
|
||||||
|
remain = remain - len(sms)
|
||||||
|
|
||||||
|
for m in sms :
|
||||||
|
if m['State'] != 'UnRead' :
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(json.dumps({
|
||||||
|
'number': m['Number'],
|
||||||
|
'at': str(m['DateTime']),
|
||||||
|
'status': m['State'],
|
||||||
|
'text': m['Text'],
|
||||||
|
}))
|
||||||
|
|
||||||
except gammu.ERR_EMPTY:
|
except gammu.ERR_EMPTY:
|
||||||
logger.debug("Finished reading all messages")
|
#do noting
|
||||||
|
return True
|
||||||
# Concat multiple SMS into list of sms that go together using LinkSMS
|
|
||||||
return gammu.LinkSMS(sms_list)
|
|
||||||
|
|
||||||
|
|
||||||
def render_sms_as_json(state_machine, sms_list, delete_sms, show_read_sms):
|
if __name__ == '__main__':
|
||||||
"""
|
main()
|
||||||
Provided sms_list is a list of lists of sms, eg
|
|
||||||
sms_list = [
|
|
||||||
[sms],
|
|
||||||
[sms1, sms2], # When two sms are in the same list, they form a long sms
|
|
||||||
[sms],
|
|
||||||
]
|
|
||||||
|
|
||||||
Concatenate long SMS from multiple sends and print them as JSON on stdout
|
|
||||||
"""
|
|
||||||
|
|
||||||
for sms in sms_list:
|
|
||||||
if sms[0]["State"] == "UnRead" or show_read_sms:
|
|
||||||
sms_text = ""
|
|
||||||
for to_concat_sms in sms:
|
|
||||||
sms_text += to_concat_sms["Text"]
|
|
||||||
print(
|
|
||||||
json.dumps(
|
|
||||||
{
|
|
||||||
"number": sms[0]["Number"],
|
|
||||||
"at": str(sms[0]["DateTime"]),
|
|
||||||
"status": sms[0]["State"],
|
|
||||||
"text": sms_text,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if delete_sms:
|
|
||||||
for to_concat_sms in sms:
|
|
||||||
try:
|
|
||||||
state_machine.DeleteSMS(
|
|
||||||
to_concat_sms["Folder"], to_concat_sms["Location"]
|
|
||||||
)
|
|
||||||
except Exception as exc:
|
|
||||||
logger.error("Cannot delete sms: %s" % exc.__str__())
|
|
||||||
|
|
||||||
|
|
||||||
def main(config_file, delete_sms, show_read):
|
|
||||||
# type: (bool, bool) -> None
|
|
||||||
logger.debug("Running gammu receiver with config {}".format(config_file))
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Mandatory modem config file
|
|
||||||
# config_file = sys.argv[1]
|
|
||||||
|
|
||||||
state_machine = get_gammu_handle(config_file)
|
|
||||||
|
|
||||||
sms_list = load_sms_from_gammu(state_machine)
|
|
||||||
render_sms_as_json(state_machine, sms_list, delete_sms, show_read)
|
|
||||||
|
|
||||||
except Exception as exc:
|
|
||||||
logger.error("Could not retrieve SMS from Gammu: %s" % exc.__str__())
|
|
||||||
logger.debug("Trace:", exc_info=True)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
parser = ArgumentParser("Gammu SMS retriever")
|
|
||||||
parser.add_argument(
|
|
||||||
"gammu_config_file", type=str, nargs="?", help="Gammu config file"
|
|
||||||
)
|
|
||||||
parser.add_argument("--debug", action="store_true", help="Activate debugging")
|
|
||||||
parser.add_argument(
|
|
||||||
"-l",
|
|
||||||
"--log-file",
|
|
||||||
type=str,
|
|
||||||
dest="log_file",
|
|
||||||
default=None,
|
|
||||||
help="Optional path to log file, defaults to /var/log",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--delete", action="store_true", help="Delete messages after they've been read"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--show-read", action="store_true", help="Also show already read messages"
|
|
||||||
)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
config_file = args.gammu_config_file
|
|
||||||
|
|
||||||
if args.log_file:
|
|
||||||
LOG_FILE = args.log_file
|
|
||||||
|
|
||||||
if args.debug:
|
|
||||||
_DEBUG = args.debug
|
|
||||||
|
|
||||||
_logger = get_logger(LOG_FILE)
|
|
||||||
if _logger:
|
|
||||||
logger = _logger
|
|
||||||
|
|
||||||
delete = False
|
|
||||||
if args.delete:
|
|
||||||
# We need to check if we have gammu >= 1.42.0 since deleting sms with lower versions fail with:
|
|
||||||
# Cannot delete sms: {'Text': 'The type of memory is not available or has been disabled.', 'Where': 'DeleteSMS', 'Code': 81}
|
|
||||||
# see https://github.com/gammu/gammu/issues/460
|
|
||||||
try:
|
|
||||||
gammu_version = get_gammu_version()
|
|
||||||
if gammu_version[0] > 1 or (gammu_version[0] == 1 and gammu_version[1] >= 42):
|
|
||||||
delete = True
|
|
||||||
else:
|
|
||||||
logger.warning("Cannot delete SMS. You need gammu >= 1.42.0.")
|
|
||||||
except TypeError:
|
|
||||||
logger.warning("Cannot get gammu version. SMS Deleting might not work properly.")
|
|
||||||
|
|
||||||
show_read = args.show_read
|
|
||||||
main(config_file, delete, show_read)
|
|
||||||
|
|
BIN
composer.phar
BIN
composer.phar
Binary file not shown.
|
@ -11,8 +11,6 @@
|
||||||
|
|
||||||
namespace controllers\internals;
|
namespace controllers\internals;
|
||||||
|
|
||||||
use DateInterval;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to call the console scripts.
|
* Class to call the console scripts.
|
||||||
*/
|
*/
|
||||||
|
@ -214,46 +212,4 @@ use DateInterval;
|
||||||
$internal_quota = new \controllers\internals\Quota($bdd);
|
$internal_quota = new \controllers\internals\Quota($bdd);
|
||||||
$internal_quota->renew_quotas();
|
$internal_quota->renew_quotas();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Do some fake population renewal.
|
|
||||||
*/
|
|
||||||
public function f()
|
|
||||||
{
|
|
||||||
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
|
|
||||||
$internal_sended = new \controllers\internals\Sended($bdd);
|
|
||||||
|
|
||||||
$destinations = ['+33612345678','+33612345679','+33612345680',];
|
|
||||||
$statuses = [\models\Sended::STATUS_DELIVERED, \models\Sended::STATUS_FAILED, \models\Sended::STATUS_UNKNOWN];
|
|
||||||
$day = new \DateTime();
|
|
||||||
$day->sub(new DateInterval('P30D'));
|
|
||||||
for ($i = 0; $i < 30; $i++)
|
|
||||||
{
|
|
||||||
$day->add(new DateInterval('P1D'));
|
|
||||||
$n = rand(0, 100);
|
|
||||||
for ($j = 0; $j < $n; $j++)
|
|
||||||
{
|
|
||||||
$id_user = 1;
|
|
||||||
$id_phone = rand(1, 2);
|
|
||||||
$destination = $destinations[array_rand($destinations)];
|
|
||||||
$status = $statuses[array_rand($statuses)];
|
|
||||||
$internal_sended->create(
|
|
||||||
$id_user,
|
|
||||||
$id_phone,
|
|
||||||
$day->format('Y-m-d H:i:s'),
|
|
||||||
"TEST N°$i:$j",
|
|
||||||
$destination,
|
|
||||||
uniqid(),
|
|
||||||
'adapters\TestAdapter',
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
[],
|
|
||||||
null,
|
|
||||||
$status,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,11 +141,8 @@ namespace controllers\internals;
|
||||||
$nb_insert = 0;
|
$nb_insert = 0;
|
||||||
|
|
||||||
$head = null;
|
$head = null;
|
||||||
$line_nb = 0;
|
|
||||||
while ($line = fgetcsv($file_handler))
|
while ($line = fgetcsv($file_handler))
|
||||||
{
|
{
|
||||||
$line_nb ++;
|
|
||||||
|
|
||||||
if (null === $head)
|
if (null === $head)
|
||||||
{
|
{
|
||||||
$head = $line;
|
$head = $line;
|
||||||
|
@ -188,16 +185,9 @@ namespace controllers\internals;
|
||||||
}
|
}
|
||||||
$data = json_encode($data);
|
$data = json_encode($data);
|
||||||
|
|
||||||
$contact_name = $line[array_keys($line)[0]];
|
|
||||||
$phone_number = \controllers\internals\Tool::parse_phone($line[array_keys($line)[1]]);
|
|
||||||
if (!$phone_number)
|
|
||||||
{
|
|
||||||
throw new \Exception('Erreur à la ligne ' . $line_nb . ' colonne 1, numéro de téléphone invalide.');
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$success = $this->create($id_user, $line[array_keys($line)[1]], $contact_name, $data);
|
$success = $this->create($id_user, $line[array_keys($line)[1]], $line[array_keys($line)[0]], $data);
|
||||||
if ($success)
|
if ($success)
|
||||||
{
|
{
|
||||||
++$nb_insert;
|
++$nb_insert;
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of RaspiSMS.
|
|
||||||
*
|
|
||||||
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
|
|
||||||
*
|
|
||||||
* This source file is subject to the GPL-3.0 license that is bundled
|
|
||||||
* with this source code in the file LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace controllers\internals;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Monolog\Handler\StreamHandler;
|
|
||||||
use Monolog\Logger;
|
|
||||||
use PHPMailer\PHPMailer\PHPMailer;
|
|
||||||
use PHPMailer\PHPMailer\SMTP;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mailing class.
|
|
||||||
*/
|
|
||||||
class LinkShortener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Shorten an URL using the configured YOURLS instance
|
|
||||||
*/
|
|
||||||
public static function shorten($url)
|
|
||||||
{
|
|
||||||
$api_url = URL_SHORTENER['HOST'] . '/yourls-api.php';
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
'action' => 'shorturl',
|
|
||||||
'format' => 'json',
|
|
||||||
'username' => URL_SHORTENER['USER'],
|
|
||||||
'password' => URL_SHORTENER['PASS'],
|
|
||||||
'url' => $url,
|
|
||||||
];
|
|
||||||
|
|
||||||
$ch = curl_init();
|
|
||||||
curl_setopt($ch, CURLOPT_URL, $api_url);
|
|
||||||
curl_setopt($ch, CURLOPT_HEADER, 0); // No header in the result
|
|
||||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Enable follow location
|
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return, do not echo result
|
|
||||||
curl_setopt($ch, CURLOPT_POST, 1); // This is a POST request
|
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
|
||||||
$response = curl_exec($ch);
|
|
||||||
curl_close($ch);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$response = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
|
|
||||||
}
|
|
||||||
catch (\Exception $e)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$shortlink = $response['shorturl'] ?? false;
|
|
||||||
return $shortlink;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,8 +11,6 @@
|
||||||
|
|
||||||
namespace controllers\internals;
|
namespace controllers\internals;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
class Received extends StandardController
|
class Received extends StandardController
|
||||||
{
|
{
|
||||||
protected $model;
|
protected $model;
|
||||||
|
@ -90,6 +88,14 @@ use Exception;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check if the received message is a SMS STOP and we must register it
|
||||||
|
$internal_smsstop = new SmsStop($this->bdd);
|
||||||
|
$is_stop = $internal_smsstop->check_for_stop($received['text']);
|
||||||
|
if ($is_stop)
|
||||||
|
{
|
||||||
|
$internal_smsstop->create($id_user, $origin);
|
||||||
|
}
|
||||||
|
|
||||||
//Link medias
|
//Link medias
|
||||||
$internal_media = new Media($this->bdd);
|
$internal_media = new Media($this->bdd);
|
||||||
foreach ($media_ids as $media_id)
|
foreach ($media_ids as $media_id)
|
||||||
|
@ -110,32 +116,6 @@ use Exception;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check if the received message is a SMS STOP and we must register it
|
|
||||||
$internal_smsstop = new SmsStop($this->bdd);
|
|
||||||
$is_stop = $internal_smsstop->check_for_stop($received['text']);
|
|
||||||
if ($is_stop)
|
|
||||||
{
|
|
||||||
$stop_exists = (bool) $internal_smsstop->get_by_number_for_user($id_user, $origin);
|
|
||||||
if ($stop_exists)
|
|
||||||
{
|
|
||||||
return $id_received;
|
|
||||||
}
|
|
||||||
|
|
||||||
$internal_smsstop->create($id_user, $origin);
|
|
||||||
|
|
||||||
//If stop response enabled, respond to user
|
|
||||||
//(this will happen only for first stop, any further stop will not trigger responses)
|
|
||||||
$internal_setting = new Setting($this->bdd);
|
|
||||||
$user_settings = $internal_setting->gets_for_user($id_user);
|
|
||||||
|
|
||||||
if ((int) ($user_settings['smsstop_respond'] ?? false))
|
|
||||||
{
|
|
||||||
$response = $user_settings['smsstop_response'];
|
|
||||||
$internal_scheduled = new Scheduled($this->bdd);
|
|
||||||
$internal_scheduled->create($id_user, (new \DateTime())->format('Y-m-d H:i:s'), $response, $id_phone, null, false, false, \models\SmsStop::SMS_STOP_TAG, [['number' => $origin, 'data' => '[]']]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $id_received;
|
return $id_received;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -451,7 +451,6 @@ use Monolog\Logger;
|
||||||
$users_settings = [];
|
$users_settings = [];
|
||||||
$users_phones = [];
|
$users_phones = [];
|
||||||
$users_phone_groups = [];
|
$users_phone_groups = [];
|
||||||
$shortlink_cache = [];
|
|
||||||
|
|
||||||
$now = new \DateTime();
|
$now = new \DateTime();
|
||||||
$now = $now->format('Y-m-d H:i:s');
|
$now = $now->format('Y-m-d H:i:s');
|
||||||
|
@ -602,10 +601,9 @@ use Monolog\Logger;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove messages to smsstops numbers if not with tag SMS_STOP
|
//Remove messages to smsstops numbers
|
||||||
if ($scheduled['tag'] != \models\SmsStop::SMS_STOP_TAG && ($users_smsstops[$id_user] ?? false) && in_array($target['number'], $users_smsstops[$id_user]))
|
if (($users_smsstops[$id_user] ?? false) && in_array($target['number'], $users_smsstops[$id_user]))
|
||||||
{
|
{
|
||||||
unset($targets[$key]);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,33 +643,6 @@ use Monolog\Logger;
|
||||||
$text = Tool::convert_to_gsm0338($text);
|
$text = Tool::convert_to_gsm0338($text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the text contain http links we must replace them
|
|
||||||
if (ENABLE_URL_SHORTENER && ((int) ($users_settings[$id_user]['shorten_url'] ?? false)))
|
|
||||||
{
|
|
||||||
$http_links = Tool::search_http_links($text);
|
|
||||||
if ($http_links !== false)
|
|
||||||
{
|
|
||||||
foreach ($http_links as $http_link)
|
|
||||||
{
|
|
||||||
if (!array_key_exists($http_link, $shortlink_cache))
|
|
||||||
{
|
|
||||||
$shortlkink = LinkShortener::shorten($http_link);
|
|
||||||
|
|
||||||
// If link shortening failed, keep original one
|
|
||||||
if ($shortlkink === false)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$shortlink_cache[$http_link] = $shortlkink;
|
|
||||||
}
|
|
||||||
|
|
||||||
$shortlink = $shortlink_cache[$http_link];
|
|
||||||
$text = str_replace($http_link, $shortlink, $text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Choose phone if no phone defined for message
|
Choose phone if no phone defined for message
|
||||||
Phones are choosen using type, priority and remaining volume :
|
Phones are choosen using type, priority and remaining volume :
|
||||||
|
|
|
@ -207,9 +207,17 @@ use Exception;
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function count_by_day_and_status_since_for_user(int $id_user, $date)
|
public function count_by_day_since_for_user(int $id_user, $date)
|
||||||
{
|
{
|
||||||
return $this->get_model()->count_by_day_and_status_since_for_user($id_user, $date);
|
$counts_by_day = $this->get_model()->count_by_day_since_for_user($id_user, $date);
|
||||||
|
$return = [];
|
||||||
|
|
||||||
|
foreach ($counts_by_day as $count_by_day)
|
||||||
|
{
|
||||||
|
$return[$count_by_day['at_ymd']] = $count_by_day['nb'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,18 +35,6 @@ namespace controllers\internals;
|
||||||
return $settings_array;
|
return $settings_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a user setting by his name for a user.
|
|
||||||
*
|
|
||||||
* @param int $id_user : user id
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function get_by_name_for_user(int $id_user, string $name)
|
|
||||||
{
|
|
||||||
return $this->get_model()->get_by_name_for_user($id_user, $name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a setting by his name and user id.
|
* Update a setting by his name and user id.
|
||||||
*
|
*
|
||||||
|
|
|
@ -73,8 +73,7 @@ namespace controllers\internals;
|
||||||
*/
|
*/
|
||||||
public function check_for_stop(string $str)
|
public function check_for_stop(string $str)
|
||||||
{
|
{
|
||||||
$str = trim(mb_strtolower($str));
|
return 'stop' == trim(mb_strtolower($str));
|
||||||
return 'stop' == $str || 'stop sms' == $str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -85,22 +85,6 @@ use BenMorel\GsmCharsetConverter\Converter;
|
||||||
return '<a href="' . self::s($url, false, true, false) . '">' . self::s($number_format, false, true, false) . '</a>';
|
return '<a href="' . self::s($url, false, true, false) . '">' . self::s($number_format, false, true, false) . '</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for http link in a text
|
|
||||||
*
|
|
||||||
* @param string $text : Text to search a link in
|
|
||||||
*
|
|
||||||
* @return bool|array : False if no link in the text, or an array of all http links
|
|
||||||
*/
|
|
||||||
public static function search_http_links($text)
|
|
||||||
{
|
|
||||||
$regex = "#http(s?)://\S+#i";
|
|
||||||
$matches = [];
|
|
||||||
$nb_matches = preg_match_all($regex, $text, $matches);
|
|
||||||
|
|
||||||
return $nb_matches > 0 ? $matches[0] : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cette fonction fait la correspondance entre un type d'evenement et une icone font awesome.
|
* Cette fonction fait la correspondance entre un type d'evenement et une icone font awesome.
|
||||||
*
|
*
|
||||||
|
|
|
@ -426,7 +426,7 @@ namespace controllers\publics;
|
||||||
$at = (string) $at;
|
$at = (string) $at;
|
||||||
$text = (string) $text;
|
$text = (string) $text;
|
||||||
|
|
||||||
if ($mms && !(int)($this->user['settings']['mms'] ?? false))
|
if (($this->user['settings']['mms'] ?? false) && $mms)
|
||||||
{
|
{
|
||||||
$return = self::DEFAULT_RETURN;
|
$return = self::DEFAULT_RETURN;
|
||||||
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
|
|
||||||
namespace controllers\publics;
|
namespace controllers\publics;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page des contacts.
|
* Page des contacts.
|
||||||
*/
|
*/
|
||||||
|
@ -347,28 +345,40 @@ use Exception;
|
||||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
//Try to import file
|
||||||
|
$invalid_type = false;
|
||||||
|
|
||||||
|
switch ($read_file['mime_type'])
|
||||||
{
|
{
|
||||||
$result = false;
|
case 'text/csv':
|
||||||
switch (true)
|
|
||||||
{
|
|
||||||
case ($read_file['mime_type'] === 'text/csv' || 'csv' === $read_file['extension']) :
|
|
||||||
$result = $this->internal_contact->import_csv($id_user, $read_file['content']);
|
$result = $this->internal_contact->import_csv($id_user, $read_file['content']);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ($read_file['mime_type'] === 'text/json' || 'json' === $read_file['extension']) :
|
case 'application/json':
|
||||||
$result = $this->internal_contact->import_json($id_user, $read_file['content']);
|
$result = $this->internal_contact->import_json($id_user, $read_file['content']);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception('Le type de fichier n\'est pas valide.');
|
if ('csv' === $read_file['extension'])
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (\Exception $e)
|
|
||||||
{
|
{
|
||||||
\FlashMessage\FlashMessage::push('danger', 'Erreur lors de l\'import: ' . $e->getMessage());
|
$result = $this->internal_contact->import_csv($id_user, $read_file['content']);
|
||||||
|
}
|
||||||
|
elseif ('json' === $read_file['extension'])
|
||||||
|
{
|
||||||
|
$result = $this->internal_contact->import_json($id_user, $read_file['content']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$invalid_type = true;
|
||||||
|
$result = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($invalid_type)
|
||||||
|
{
|
||||||
|
\FlashMessage\FlashMessage::push('danger', 'Le type de fichier n\'est pas valide.');
|
||||||
|
|
||||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,12 +87,11 @@ namespace controllers\publics;
|
||||||
$stats_start_date_formated = $stats_start_date->format('Y-m-d');
|
$stats_start_date_formated = $stats_start_date->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
$nb_sendeds_by_day = $this->internal_sended->count_by_day_and_status_since_for_user($id_user, $stats_start_date_formated);
|
$nb_sendeds_by_day = $this->internal_sended->count_by_day_since_for_user($id_user, $stats_start_date_formated);
|
||||||
$nb_receiveds_by_day = $this->internal_received->count_by_day_since_for_user($id_user, $stats_start_date_formated);
|
$nb_receiveds_by_day = $this->internal_received->count_by_day_since_for_user($id_user, $stats_start_date_formated);
|
||||||
|
|
||||||
//On va traduire ces données pour les afficher en graphique
|
//On va traduire ces données pour les afficher en graphique
|
||||||
$array_bar_chart_sended = [];
|
$array_area_chart = [];
|
||||||
$array_bar_chart_received = [];
|
|
||||||
|
|
||||||
$date = clone $stats_start_date;
|
$date = clone $stats_start_date;
|
||||||
$one_day = new \DateInterval('P1D');
|
$one_day = new \DateInterval('P1D');
|
||||||
|
@ -102,15 +101,12 @@ namespace controllers\publics;
|
||||||
while ($date <= $now)
|
while ($date <= $now)
|
||||||
{
|
{
|
||||||
$date_f = $date->format('Y-m-d');
|
$date_f = $date->format('Y-m-d');
|
||||||
$array_bar_chart_sended[$date_f] = [
|
$array_area_chart[$date_f] = [
|
||||||
'period' => $date_f,
|
'period' => $date_f,
|
||||||
'sendeds_failed' => 0,
|
'sendeds' => 0,
|
||||||
'sendeds_unknown' => 0,
|
'receiveds' => 0,
|
||||||
'sendeds_delivered' => 0,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$array_bar_chart_received[$date_f] = ['period' => $date_f, 'receiveds' => 0];
|
|
||||||
|
|
||||||
$date->add($one_day);
|
$date->add($one_day);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,16 +114,15 @@ namespace controllers\publics;
|
||||||
$total_receiveds = 0;
|
$total_receiveds = 0;
|
||||||
|
|
||||||
//0n remplie le tableau avec les données adaptées
|
//0n remplie le tableau avec les données adaptées
|
||||||
foreach ($nb_sendeds_by_day as $nb_sended)
|
foreach ($nb_sendeds_by_day as $date => $nb_sended)
|
||||||
{
|
{
|
||||||
$array_bar_chart_sended[$nb_sended['at_ymd']]['sendeds_' . $nb_sended['status']] = $nb_sended['nb'];
|
$array_area_chart[$date]['sendeds'] = $nb_sended;
|
||||||
$array_bar_chart_sended[$nb_sended['at_ymd']]['sendeds_total'] = ($array_bar_chart_sended[$nb_sended['at_ymd']]['sendeds_total'] ?? 0) + $nb_sended['nb'];
|
$total_sendeds += $nb_sended;
|
||||||
$total_sendeds += $nb_sended['nb'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($nb_receiveds_by_day as $date => $nb_received)
|
foreach ($nb_receiveds_by_day as $date => $nb_received)
|
||||||
{
|
{
|
||||||
$array_bar_chart_received[$date]['receiveds'] = $nb_received;
|
$array_area_chart[$date]['receiveds'] = $nb_received;
|
||||||
$total_receiveds += $nb_received;
|
$total_receiveds += $nb_received;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +130,7 @@ namespace controllers\publics;
|
||||||
$avg_sendeds = round($total_sendeds / $nb_days, 2);
|
$avg_sendeds = round($total_sendeds / $nb_days, 2);
|
||||||
$avg_receiveds = round($total_receiveds / $nb_days, 2);
|
$avg_receiveds = round($total_receiveds / $nb_days, 2);
|
||||||
|
|
||||||
$array_bar_chart_sended = array_values($array_bar_chart_sended);
|
$array_area_chart = array_values($array_area_chart);
|
||||||
$array_bar_chart_received = array_values($array_bar_chart_received);
|
|
||||||
|
|
||||||
$this->render('dashboard/show', [
|
$this->render('dashboard/show', [
|
||||||
'nb_contacts' => $nb_contacts,
|
'nb_contacts' => $nb_contacts,
|
||||||
|
@ -151,9 +145,7 @@ namespace controllers\publics;
|
||||||
'sendeds' => $sendeds,
|
'sendeds' => $sendeds,
|
||||||
'receiveds' => $receiveds,
|
'receiveds' => $receiveds,
|
||||||
'events' => $events,
|
'events' => $events,
|
||||||
'data_bar_chart_sended' => json_encode($array_bar_chart_sended),
|
'data_area_chart' => json_encode($array_area_chart),
|
||||||
'data_bar_chart_received' => json_encode($array_bar_chart_received),
|
|
||||||
'stats_start_date_formated' => $stats_start_date_formated,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,20 +75,6 @@ namespace controllers\publics;
|
||||||
$setting_value = json_encode($setting_value);
|
$setting_value = json_encode($setting_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If setting dont exists yet, create it, else update
|
|
||||||
$setting = $this->internal_setting->get_by_name_for_user($_SESSION['user']['id'], $setting_name);
|
|
||||||
if (!$setting)
|
|
||||||
{
|
|
||||||
$success = $this->internal_setting->create($_SESSION['user']['id'], $setting_name, $setting_value);
|
|
||||||
if (false === $success)
|
|
||||||
{
|
|
||||||
\FlashMessage\FlashMessage::push('danger', 'Impossible de mettre à jour ce réglage.');
|
|
||||||
|
|
||||||
return $this->redirect(\descartes\Router::url('Setting', 'show'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$update_setting_result = $this->internal_setting->update_for_user($_SESSION['user']['id'], $setting_name, $setting_value);
|
$update_setting_result = $this->internal_setting->update_for_user($_SESSION['user']['id'], $setting_name, $setting_value);
|
||||||
if (false === $update_setting_result)
|
if (false === $update_setting_result)
|
||||||
{
|
{
|
||||||
|
@ -96,7 +82,6 @@ namespace controllers\publics;
|
||||||
|
|
||||||
return $this->redirect(\descartes\Router::url('Setting', 'show'));
|
return $this->redirect(\descartes\Router::url('Setting', 'show'));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$settings = $this->internal_setting->gets_for_user($_SESSION['user']['id']);
|
$settings = $this->internal_setting->gets_for_user($_SESSION['user']['id']);
|
||||||
$_SESSION['user']['settings'] = $settings;
|
$_SESSION['user']['settings'] = $settings;
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Phinx\Migration\AbstractMigration;
|
|
||||||
|
|
||||||
class AddIndexToSmsTimestamps extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Add indexes on most SMS table timestamp (and possibly other fields) to improve perfs on query using date, like stats, sending limits, etc.
|
|
||||||
*/
|
|
||||||
public function change()
|
|
||||||
{
|
|
||||||
$table = $this->table('sended');
|
|
||||||
$table->addIndex('at');
|
|
||||||
$table->update();
|
|
||||||
|
|
||||||
$table = $this->table('received');
|
|
||||||
$table->addIndex('at');
|
|
||||||
$table->update();
|
|
||||||
|
|
||||||
$table = $this->table('scheduled');
|
|
||||||
$table->addIndex('at');
|
|
||||||
$table->update();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Phinx\Migration\AbstractMigration;
|
|
||||||
|
|
||||||
class AddIndexOnSendedUid extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Modify sended uid and call to be 100 char long, we dont need a 500 char uid and too long a char ss hurting perfs
|
|
||||||
* Add index on sended uid to make status update more efficient
|
|
||||||
*/
|
|
||||||
public function change()
|
|
||||||
{
|
|
||||||
$table = $this->table('sended');
|
|
||||||
$table->changeColumn('uid', 'string', ['limit' => 100]);
|
|
||||||
$table->addIndex('uid');
|
|
||||||
$table->update();
|
|
||||||
|
|
||||||
|
|
||||||
$table = $this->table('call');
|
|
||||||
$table->changeColumn('uid', 'string', ['limit' => 100]);
|
|
||||||
$table->addIndex('uid');
|
|
||||||
$table->update();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -91,21 +91,21 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cette fonction permet de faire un retour sous forme de json
|
* Cette fonction permet de faire un retour sous forme de json
|
||||||
* @param array $datas : Les données à retourner sous forme de json
|
* @param array $data : Les données à retourner sous forme de json
|
||||||
* @param boolean $secure : Défini si l'affichage doit être sécurisé contre les XSS, par défaut true
|
* @param boolean $secure : Défini si l'affichage doit être sécurisé contre les XSS, par défaut true
|
||||||
* @return ApiController : On retourne l'API controlleur lui meme pour pouvoir chainer
|
* @return ApiController : On retourne l'API controlleur lui meme pour pouvoir chainer
|
||||||
*/
|
*/
|
||||||
public function json ($datas, $secure = true)
|
public function json ($data, $secure = true)
|
||||||
{
|
{
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
if ($secure)
|
if ($secure)
|
||||||
{
|
{
|
||||||
echo htmlspecialchars(json_encode($datas), ENT_NOQUOTES);
|
echo htmlspecialchars(json_encode($data), ENT_NOQUOTES);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
echo json_encode($datas);
|
echo json_encode($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
if (!is_readable($template_path))
|
if (!is_readable($template_path))
|
||||||
{
|
{
|
||||||
throw new exceptions\DescartesExceptionTemplateNotReadable('Template ' . $template_path . ' is not readable.');
|
throw new DescartesTemplateNotReadableException('Template ' . $template_path . ' is not readable.');
|
||||||
}
|
}
|
||||||
|
|
||||||
require $template_path;
|
require $template_path;
|
||||||
|
|
|
@ -72,7 +72,8 @@
|
||||||
protected static function clean_url (string $url)
|
protected static function clean_url (string $url)
|
||||||
{
|
{
|
||||||
$to_remove = parse_url(HTTP_PWD, PHP_URL_PATH);
|
$to_remove = parse_url(HTTP_PWD, PHP_URL_PATH);
|
||||||
$url = mb_strcut($url, $to_remove ? mb_strlen($to_remove) : 0);
|
|
||||||
|
$url = mb_strcut($url, mb_strlen($to_remove));
|
||||||
$url = parse_url($url, PHP_URL_PATH);
|
$url = parse_url($url, PHP_URL_PATH);
|
||||||
|
|
||||||
return $url;
|
return $url;
|
||||||
|
@ -251,7 +252,6 @@
|
||||||
|
|
||||||
$type = $parameter->getType();
|
$type = $parameter->getType();
|
||||||
$type = $type ?? false;
|
$type = $type ?? false;
|
||||||
$type = ($type instanceof \ReflectionNamedType) ? $type->getName() : $type;
|
|
||||||
|
|
||||||
if ($type)
|
if ($type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,31 +4,24 @@
|
||||||
/*
|
/*
|
||||||
* Define Descartes env
|
* Define Descartes env
|
||||||
*/
|
*/
|
||||||
$http_dir_path = ''; //Path we need to put after servername in url to access app
|
$http_dir_path = '/raspisms'; //Path we need to put after servername in url to access app
|
||||||
$https = $_SERVER['HTTPS'] ?? 0;
|
$http_protocol = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://';
|
||||||
|
$http_server_name = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost';
|
||||||
|
$http_server_port = isset($_SERVER['SERVER_PORT']) ? ($_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'] : '';
|
||||||
|
$https = $_SERVER['HTTPS'] ?? false;
|
||||||
|
|
||||||
// Check for proxy forward
|
if ( !isset($_SERVER['SERVER_PORT']) || ($_SERVER['SERVER_PORT'] == 80 && !$https) || ($_SERVER['SERVER_PORT'] == 443 && $https) )
|
||||||
$forwarded_https = ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? $_SERVER['HTTP_FORWARDED_PROTO'] ?? NULL) == 'https';
|
|
||||||
$forwarded_ssl = ($_SERVER['HTTP_X_FORWARDED_SSL'] ?? NULL) == 'on';
|
|
||||||
$proxy = $forwarded_https || $forwarded_ssl;
|
|
||||||
|
|
||||||
$http_protocol = 'http://';
|
|
||||||
if ($https)
|
|
||||||
{
|
{
|
||||||
$http_protocol = 'https://';
|
$http_server_port = '';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$http_server_port = ':' . $_SERVER['SERVER_PORT'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$http_server_name = $_SERVER['SERVER_NAME'] ?? 'localhost';
|
|
||||||
|
|
||||||
// Check port to only set it if not default port
|
|
||||||
$port = $_SERVER['SERVER_PORT'] ?? '';
|
|
||||||
$port = ($port == 80 && !$https) ? '' : $port;
|
|
||||||
$port = ($port == 443 && $https) ? '' : $port;
|
|
||||||
$port = $proxy ? '' : $port;
|
|
||||||
$http_server_port = $port ? ':' . $port : '';
|
|
||||||
|
|
||||||
|
|
||||||
$pwd = substr(__DIR__, 0, strrpos(__DIR__, '/'));
|
$pwd = substr(__DIR__, 0, strrpos(__DIR__, '/'));
|
||||||
|
$http_pwd = $http_protocol . $http_server_name . $http_server_port . $http_dir_path;
|
||||||
|
|
||||||
|
|
||||||
$env = [
|
$env = [
|
||||||
|
@ -38,6 +31,7 @@
|
||||||
'HTTP_SERVER_NAME' => $http_server_name,
|
'HTTP_SERVER_NAME' => $http_server_name,
|
||||||
'HTTP_SERVER_PORT' => $http_server_port,
|
'HTTP_SERVER_PORT' => $http_server_port,
|
||||||
'PWD' => $pwd,
|
'PWD' => $pwd,
|
||||||
|
'HTTP_PWD' => $http_pwd,
|
||||||
|
|
||||||
//path of back resources
|
//path of back resources
|
||||||
'PWD_CONTROLLER' => $pwd . '/controllers', //Controllers dir
|
'PWD_CONTROLLER' => $pwd . '/controllers', //Controllers dir
|
||||||
|
@ -46,17 +40,22 @@
|
||||||
|
|
||||||
//path of front resources
|
//path of front resources
|
||||||
'PWD_ASSETS' => $pwd . '/assets', //Assets dir
|
'PWD_ASSETS' => $pwd . '/assets', //Assets dir
|
||||||
|
'HTTP_PWD_ASSETS' => $http_pwd . '/assets', //HTTP path of asset dir
|
||||||
|
|
||||||
//images
|
//images
|
||||||
'PWD_IMG' => $pwd . '/assets' . '/img',
|
'PWD_IMG' => $pwd . '/assets' . '/img',
|
||||||
|
'HTTP_PWD_IMG' => $http_pwd . '/assets' . '/img',
|
||||||
|
|
||||||
//css
|
//css
|
||||||
'PWD_CSS' => $pwd . '/assets' . '/css',
|
'PWD_CSS' => $pwd . '/assets' . '/css',
|
||||||
|
'HTTP_PWD_CSS' => $http_pwd . '/assets' . '/css',
|
||||||
|
|
||||||
//javascript
|
//javascript
|
||||||
'PWD_JS' => $pwd . '/assets' . '/js',
|
'PWD_JS' => $pwd . '/assets' . '/js',
|
||||||
|
'HTTP_PWD_JS' => $http_pwd . '/assets' . '/js',
|
||||||
|
|
||||||
//fonts
|
//fonts
|
||||||
'PWD_FONT' => $pwd . '/assets' . '/font',
|
'PWD_FONT' => $pwd . '/assets' . '/font',
|
||||||
|
'HTTP_PWD_FONT' => $http_pwd . '/assets' . '/font',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
$environment = [];
|
$environment = [];
|
||||||
$env = [];
|
$env = [];
|
||||||
|
|
||||||
// Load descartes base env
|
|
||||||
require_once(__DIR__ . '/env.php');
|
require_once(__DIR__ . '/env.php');
|
||||||
$environment = array_merge($environment, $env);
|
$environment = array_merge($environment, $env);
|
||||||
|
|
||||||
|
@ -32,8 +31,11 @@
|
||||||
$environment = array_merge($environment, $env);
|
$environment = array_merge($environment, $env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Define all Descartes constants
|
||||||
|
define_array($environment);
|
||||||
|
|
||||||
### GLOBAL ENV ###
|
### GLOBAL ENV ###
|
||||||
//Load global app env
|
$environment = [];
|
||||||
$env = [];
|
$env = [];
|
||||||
if (file_exists(__DIR__ . '/../env.php'))
|
if (file_exists(__DIR__ . '/../env.php'))
|
||||||
{
|
{
|
||||||
|
@ -41,30 +43,19 @@
|
||||||
$environment = array_merge($environment, $env);
|
$environment = array_merge($environment, $env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define_array($environment);
|
||||||
|
|
||||||
|
|
||||||
### SPECIFIC ENV ###
|
### SPECIFIC ENV ###
|
||||||
// Load specific environment env
|
$environment = [];
|
||||||
$env = [];
|
$env = [];
|
||||||
if (isset($environment['ENV']) && file_exists(__DIR__ . '/../env.' . $environment['ENV'] . '.php'))
|
|
||||||
|
if (defined('ENV') && file_exists(__DIR__ . '/../env.' . ENV . '.php'))
|
||||||
{
|
{
|
||||||
require_once(__DIR__ . '/../env.' . $environment['ENV'] . '.php');
|
require_once(__DIR__ . '/../env.' . ENV . '.php');
|
||||||
$environment = array_merge($environment, $env);
|
$environment = array_merge($environment, $env);
|
||||||
}
|
}
|
||||||
|
|
||||||
### BUILD HTTP PWD CONSTS ###
|
|
||||||
// We compute http pwd at last minute to allow for simple overriding by user
|
|
||||||
// by simply defining custom HTTP_* (PROTOCOL, SERVER_NAME, SERVER_PORT, DIR_PATH)
|
|
||||||
$http_pwd = $environment['HTTP_PROTOCOL'] . $environment['HTTP_SERVER_NAME'] . $environment['HTTP_SERVER_PORT'] . $environment['HTTP_DIR_PATH'];
|
|
||||||
$env = [
|
|
||||||
"HTTP_PWD" => $http_pwd,
|
|
||||||
'HTTP_PWD_ASSETS' => $http_pwd . '/assets', //HTTP path of asset dir
|
|
||||||
'HTTP_PWD_IMG' => $http_pwd . '/assets' . '/img',
|
|
||||||
'HTTP_PWD_CSS' => $http_pwd . '/assets' . '/css',
|
|
||||||
'HTTP_PWD_JS' => $http_pwd . '/assets' . '/js',
|
|
||||||
'HTTP_PWD_FONT' => $http_pwd . '/assets' . '/font',
|
|
||||||
];
|
|
||||||
$environment = array_merge($environment, $env);
|
|
||||||
|
|
||||||
define_array($environment);
|
define_array($environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
env.php.dist
24
env.php.dist
|
@ -2,31 +2,28 @@
|
||||||
/*
|
/*
|
||||||
This file define constants and options for the app
|
This file define constants and options for the app
|
||||||
*/
|
*/
|
||||||
$dir_path = '/raspisms';
|
|
||||||
$http_pwd = $environment['HTTP_PROTOCOL'] . $dir_path . $environment['HTTP_SERVER_PORT'] . $environment['HTTP_DIR_PATH'];
|
|
||||||
$env = [
|
$env = [
|
||||||
'ENV' => '%APP_ENV%', #env name (probably 'dev' or 'prod'), this value is used to get the env.XXX.php.dist matching env file
|
'ENV' => '%APP_ENV%', #env name (probably 'dev' or 'prod'), this value is used to get the env.XXX.php.dist matching env file
|
||||||
'SESSION_NAME' => 'raspisms',
|
'SESSION_NAME' => 'raspisms',
|
||||||
'HTTP_DIR_PATH' => $dir_path, // Override default dir path
|
|
||||||
|
|
||||||
//RaspiSMS settings
|
//RaspiSMS settings
|
||||||
'WEBSITE_TITLE' => 'RaspiSMS',
|
'WEBSITE_TITLE' => 'RaspiSMS',
|
||||||
'WEBSITE_DESCRIPTION' => '',
|
'WEBSITE_DESCRIPTION' => '',
|
||||||
'WEBSITE_AUTHOR' => 'Raspberry Pi FR',
|
'WEBSITE_AUTHOR' => 'Raspberry Pi FR',
|
||||||
'PWD_SCRIPTS' => $environment['PWD'] . '/scripts',
|
'PWD_SCRIPTS' => PWD . '/scripts',
|
||||||
'PWD_RECEIVEDS' => $environment['PWD'] . '/receiveds',
|
'PWD_RECEIVEDS' => PWD . '/receiveds',
|
||||||
'HTTP_PWD_SOUND' => $http_pwd . '/assets' . '/sounds',
|
'HTTP_PWD_SOUND' => HTTP_PWD_ASSETS . '/sounds',
|
||||||
'PWD_ADAPTERS' => $environment['PWD'] . '/adapters',
|
'PWD_ADAPTERS' => PWD . '/adapters',
|
||||||
'PWD_DATA' => $environment['PWD'] . '/data',
|
'PWD_DATA' => PWD . '/data',
|
||||||
'HTTP_PWD_DATA' => $http_pwd . '/data',
|
'HTTP_PWD_DATA' => HTTP_PWD . '/data',
|
||||||
'PWD_DATA_PUBLIC' => $environment['PWD'] . '/data/public',
|
'PWD_DATA_PUBLIC' => PWD . '/data/public',
|
||||||
'HTTP_PWD_DATA_PUBLIC' => $http_pwd . '/data/public',
|
'HTTP_PWD_DATA_PUBLIC' => HTTP_PWD . '/data/public',
|
||||||
'PWD_LOGS' => '/var/log/raspisms',
|
'PWD_LOGS' => '/var/log/raspisms',
|
||||||
'PWD_PID' => '/var/run/raspisms',
|
'PWD_PID' => '/var/run/raspisms',
|
||||||
'APP_SECRET' => '%APP_SECRET%',
|
'APP_SECRET' => '%APP_SECRET%',
|
||||||
'ENABLE_COMMAND' => false,
|
'ENABLE_COMMAND' => false,
|
||||||
'ENABLE_ACCOUNT_DELETION' => true,
|
'ENABLE_ACCOUNT_DELETION' => true,
|
||||||
'ENABLE_URL_SHORTENER' => %APP_URL_SHORTENER%,
|
|
||||||
|
|
||||||
//E-mail types
|
//E-mail types
|
||||||
'EMAIL_RESET_PASSWORD' => [
|
'EMAIL_RESET_PASSWORD' => [
|
||||||
|
@ -88,9 +85,6 @@
|
||||||
'force_gsm_alphabet' => 0,
|
'force_gsm_alphabet' => 0,
|
||||||
'phone_limit' => 0,
|
'phone_limit' => 0,
|
||||||
'phone_priority' => 0,
|
'phone_priority' => 0,
|
||||||
'shorten_url' => 0,
|
|
||||||
'smsstop_respond' => 1,
|
|
||||||
'smsstop_response' => 'Demande prise en compte, vous ne recevrez plus de messages.',
|
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,4 @@
|
||||||
'FROM' => '%APP_MAIL_FROM%',
|
'FROM' => '%APP_MAIL_FROM%',
|
||||||
],
|
],
|
||||||
|
|
||||||
//YOURLS url shortener settings
|
|
||||||
'URL_SHORTENER' => [
|
|
||||||
'HOST' => '%APP_URL_SHORTENER_HOST%',
|
|
||||||
'USER' => '%APP_URL_SHORTENER_USER%',
|
|
||||||
'PASS' => '%APP_URL_SHORTENER_PASS%',
|
|
||||||
]
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -222,14 +222,14 @@ namespace models;
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function count_by_day_and_status_since_for_user($id_user, $date)
|
public function count_by_day_since_for_user($id_user, $date)
|
||||||
{
|
{
|
||||||
$query = "
|
$query = "
|
||||||
SELECT COUNT(id) as nb, status, DATE_FORMAT(at, '%Y-%m-%d') as at_ymd
|
SELECT COUNT(id) as nb, DATE_FORMAT(at, '%Y-%m-%d') as at_ymd
|
||||||
FROM sended
|
FROM sended
|
||||||
WHERE at > :date
|
WHERE at > :date
|
||||||
AND id_user = :id_user
|
AND id_user = :id_user
|
||||||
GROUP BY at_ymd, status
|
GROUP BY at_ymd
|
||||||
";
|
";
|
||||||
|
|
||||||
$params = [
|
$params = [
|
||||||
|
|
|
@ -27,18 +27,6 @@ namespace models;
|
||||||
return $this->_update($this->get_table_name(), ['value' => $value], ['id_user' => $id_user, 'name' => $name]);
|
return $this->_update($this->get_table_name(), ['value' => $value], ['id_user' => $id_user, 'name' => $name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a user setting by his name for a user.
|
|
||||||
*
|
|
||||||
* @param int $id_user : user id
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function get_by_name_for_user(int $id_user, string $name)
|
|
||||||
{
|
|
||||||
return $this->_select_one($this->get_table_name(), ['name' => $name, 'id_user' => $id_user]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return table name.
|
* Return table name.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -13,8 +13,6 @@ namespace models;
|
||||||
|
|
||||||
class SmsStop extends StandardModel
|
class SmsStop extends StandardModel
|
||||||
{
|
{
|
||||||
const SMS_STOP_TAG = 'SMS_STOP';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a smsstop by his number and user.
|
* Return a smsstop by his number and user.
|
||||||
*
|
*
|
||||||
|
|
|
@ -120,29 +120,16 @@
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="panel panel-default dashboard-panel-chart">
|
<div class="panel panel-default dashboard-panel-chart">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h3 class="panel-title"><i class="fa fa-area-chart fa-fw"></i> SMS envoyés depuis le <?= $stats_start_date_formated; ?> : </h3>
|
<h3 class="panel-title"><i class="fa fa-area-chart fa-fw"></i> Activité de la semaine : </h3>
|
||||||
<span style="color: #5CB85C;">SMS envoyés (moyenne = <?php echo $avg_sendeds; ?> par jour).</span><br/>
|
<span style="color: #5CB85C;">SMS envoyés (moyenne = <?php echo $avg_sendeds; ?> par jour).</span><br/>
|
||||||
|
<span style="color: #EDAB4D">SMS reçus (moyenne = <?php echo $avg_receiveds; ?> par jour).</span>
|
||||||
<?php if ($quota_unused) { ?>
|
<?php if ($quota_unused) { ?>
|
||||||
<br/>
|
<br/>
|
||||||
<span style="color: #d9534f">Crédits restants : <?= $quota_unused; ?>.</span>
|
<span style="color: #d9534f">Crédits restants : <?= $quota_unused; ?>.</span>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div id="morris-bar-chart-sended"></div>
|
<div id="morris-area-chart"></div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="panel panel-default dashboard-panel-chart">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h3 class="panel-title"><i class="fa fa-area-chart fa-fw"></i> SMS reçus depuis le <?= $stats_start_date_formated; ?> : </h3>
|
|
||||||
<span style="color: #EDAB4D">SMS reçus (moyenne = <?php echo $avg_receiveds; ?> par jour).</span>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div id="morris-bar-chart-received"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -257,54 +244,22 @@
|
||||||
<script>
|
<script>
|
||||||
jQuery(document).ready(function()
|
jQuery(document).ready(function()
|
||||||
{
|
{
|
||||||
Morris.Bar({
|
Morris.Area({
|
||||||
element: 'morris-bar-chart-sended',
|
element: 'morris-area-chart',
|
||||||
|
behaveLikeLine: true,
|
||||||
fillOpacity: 0.4,
|
fillOpacity: 0.4,
|
||||||
data: <?php echo $data_bar_chart_sended;?>,
|
data: <?php echo $data_area_chart;?>,
|
||||||
xkey: 'period',
|
xkey: 'period',
|
||||||
parseTime: false,
|
parseTime: false,
|
||||||
ykeys: ['sendeds_failed', 'sendeds_unknown', 'sendeds_delivered'],
|
ykeys: ['sendeds', 'receiveds'],
|
||||||
labels: ['SMS échoués', 'SMS inconnus', 'SMS délivrés'],
|
labels: ['SMS envoyés', 'SMS reçus'],
|
||||||
barColors: ['#D9534F', '#337AB7', '#5CB85C'],
|
lineColors: ['#5CB85C', '#EDAB4D'],
|
||||||
goals: [<?php echo $avg_sendeds; ?>,],
|
goals: [<?php echo $avg_sendeds; ?>, <?php echo $avg_receiveds; ?>],
|
||||||
goalLineColors: ['#5CB85C'],
|
goalLineColors: ['#5CB85C', '#EDAB4D'],
|
||||||
goalStrokeWidth: 2,
|
goalStrokeWidth: 2,
|
||||||
pointSize: 4,
|
pointSize: 4,
|
||||||
hideHover: 'auto',
|
hideHover: 'auto',
|
||||||
resize: true,
|
resize: true
|
||||||
stacked: true,
|
|
||||||
hoverCallback: function (index, options, content, row) {
|
|
||||||
ret = '';
|
|
||||||
for (i = 0; i < options.ykeys.length; i++)
|
|
||||||
{
|
|
||||||
ret += options.labels[i];
|
|
||||||
ret += ' : ';
|
|
||||||
ret += row[options.ykeys[i]];
|
|
||||||
ret += ' (';
|
|
||||||
ret += (row[options.ykeys[i]] / (row.sendeds_total ? row.sendeds_total : 1) * 100).toFixed(2);
|
|
||||||
ret += '%)';
|
|
||||||
ret += "<br/>";
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Morris.Bar({
|
|
||||||
element: 'morris-bar-chart-received',
|
|
||||||
fillOpacity: 0.4,
|
|
||||||
data: <?php echo $data_bar_chart_received;?>,
|
|
||||||
xkey: 'period',
|
|
||||||
parseTime: false,
|
|
||||||
ykeys: ['receiveds'],
|
|
||||||
labels: ['SMS reçus'],
|
|
||||||
barColors: ['#EDAB4D'],
|
|
||||||
goals: [<?php echo $avg_receiveds; ?>],
|
|
||||||
goalLineColors: ['#EDAB4D'],
|
|
||||||
goalStrokeWidth: 2,
|
|
||||||
pointSize: 4,
|
|
||||||
hideHover: 'auto',
|
|
||||||
resize: true,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -161,16 +161,6 @@
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
}
|
}
|
||||||
else if (field.type == 'textarea')
|
|
||||||
{
|
|
||||||
html += '<div class="form-group">' +
|
|
||||||
'<label>' + field.title + '</label>' +
|
|
||||||
'<p class="italic small help">' + field.description + '</p>' +
|
|
||||||
'<div class="form-group">' +
|
|
||||||
'<textarea name="adapter_data[' + field.name + ']" class="form-control" ' + (field.required ? 'required' : '') + ' >' + (field.default_value ? field.default_value : '') + '</textarea>' +
|
|
||||||
'</div>' +
|
|
||||||
'</div>';
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
html += '<div class="form-group">' +
|
html += '<div class="form-group">' +
|
||||||
|
|
|
@ -225,16 +225,6 @@
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
}
|
}
|
||||||
else if (field.type == 'textarea')
|
|
||||||
{
|
|
||||||
html += '<div class="form-group">' +
|
|
||||||
'<label>' + field.title + '</label>' +
|
|
||||||
'<p class="italic small help">' + field.description + '</p>' +
|
|
||||||
'<div class="form-group">' +
|
|
||||||
'<textarea name="adapter_data[' + field.name + ']" class="form-control" ' + (field.required ? 'required' : '') + ' >' + (value ? value : '') + '</textarea>' +
|
|
||||||
'</div>' +
|
|
||||||
'</div>';
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
html += '' +
|
html += '' +
|
||||||
|
|
|
@ -113,30 +113,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if (ENABLE_URL_SHORTENER) { ?>
|
|
||||||
<div class="col-xs-12 col-md-6">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h4 class="panel-title"><i class="fa fa-link fa-fw"></i> Support du raccourcisseur d'URL</h4>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'shorten_url', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Raccourcir automatiquement les liens HTTP(S) dans les SMS : </label>
|
|
||||||
<select name="setting_value" class="form-control">
|
|
||||||
<option value="0">Non</option>
|
|
||||||
<option value="1" <?php echo $_SESSION['user']['settings']['shorten_url'] ? 'selected' : ''; ?>>Oui</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<button class="btn btn-success">Mettre à jour les données</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php } ?>
|
|
||||||
|
|
||||||
<div class="col-xs-12 col-md-6">
|
<div class="col-xs-12 col-md-6">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
@ -203,47 +179,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-xs-12 col-md-6">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h4 class="panel-title"><i class="fa fa-ban fa-fw"></i> Activation des réponses automatiques aux SMS-STOP</h4>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'smsstop_respond', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Réponses automatiques aux SMS STOP activées : </label>
|
|
||||||
<select name="setting_value" class="form-control">
|
|
||||||
<option value="0">Non</option>
|
|
||||||
<option value="1" <?php echo $_SESSION['user']['settings']['smsstop_respond'] ? 'selected' : ''; ?>>Oui</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<button class="btn btn-success">Mettre à jour les données</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-xs-12 col-md-6">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<h4 class="panel-title"><i class="fa fa-comments-o fa-fw"></i> Texte de réponse aux SMS-STOP</h4>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'smsstop_response', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Texte des réponses automatiques aux SMS-STOP : </label>
|
|
||||||
<input name="setting_value" class="form-control" value="<?php $this->s($_SESSION['user']['settings']['smsstop_response'] ?? ''); ?>" />
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<button class="btn btn-success">Mettre à jour les données</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-xs-12 col-md-6">
|
<div class="col-xs-12 col-md-6">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
|
Loading…
Reference in New Issue