Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions schema/data-actions.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
["SIS", "selector.set"],
["SIS", "selector.query"],
["SIS", "news"],
["SIS", "whatsapp.incoming"],
["Stats", "mostMessagedTimeslotYear"],
["Stats", "mostListenedTimeslotYear"],
["Stats", "mostListenedShowYear"],
Expand Down
1 change: 1 addition & 0 deletions schema/data-actionsauth.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
["SIS", "tracklist.findTrack", "AUTH_USESIS"],
["SIS", "webcam.get", "AUTH_USESIS"],
["SIS", "webcam.set", "AUTH_MODIFYWEBCAM"],
["SIS", "whatsapp.incoming", "AUTH_NOLOGIN"],
["Stats", "bapsPlayCounter", "AUTH_TRACKSTATISTICS"],
["Stats", "fullTracklist", "AUTH_TRACKSTATISTICS"],
["Stats", "jukeboxPlayCounter", "AUTH_TRACKSTATISTICS"],
Expand Down
1 change: 1 addition & 0 deletions schema/patches/19.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO commtype (descr) VALUES ('WhatsApp');
4 changes: 4 additions & 0 deletions src/Classes/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,10 @@ final class Config
public static $autoviz_clips_path = '';
public static $autoviz_public_clips_base = '/media/autoviz-clips';

public static $sis_whatsapp_enable = false;
public static $sis_whatsapp_verify_token = '';
public static $sis_whatsapp_api_token = '';

/**
* Array of tabs and plugins to be used by SIS. They will be loaded in order.
*/
Expand Down
51 changes: 49 additions & 2 deletions src/Classes/ServiceAPI/MyRadio_Timeslot.php
Original file line number Diff line number Diff line change
Expand Up @@ -1343,7 +1343,8 @@ public function getMessages($offset = 0)
subject AS title,
content AS body,
(statusid = 2) AS read,
comm_source AS source
comm_source AS source,
sender AS sender
FROM sis2.messages c
INNER JOIN schedule.show_season_timeslot ts ON (c.timeslotid = ts.show_season_timeslot_id)
WHERE statusid <= 2 AND c.timeslotid = $1
Expand All @@ -1357,11 +1358,14 @@ public function getMessages($offset = 0)
$result[$k]['time'] = intval($v['time']);
$result[$k]['id'] = intval($v['id']);
//Add the IP metadata
if ($v['type'] == 3) {
if ($v['type'] === 3) {
$result[$k]['location'] = SIS_Utils::ipLookup($v['source']);
}
$result[$k]['title'] = htmlspecialchars($v['title']);
$result[$k]['body'] = htmlspecialchars($v['body']);
if ($v['type'] === 6) {
$result[$k]['author'] = htmlspecialchars($v['sender']);
}
}

return $result;
Expand Down Expand Up @@ -1409,6 +1413,49 @@ public function sendMessage($message)
return $this;
}

/**
* Sends a message to the timeslot for display in SIS.
*
* @param string $message the message to be sent
* @param $sender
* @param $number
* @return MyRadio_Timeslot
*/
public function sendWhatsappMessage($message, $sender, $number): MyRadio_Timeslot
{
$message = trim($message);

if (empty($message)) {
throw new MyRadioException('Message is empty.', 400);
}

$junk = SIS_Utils::checkMessageSpam($message);
$warning = SIS_Utils::checkMessageSocialEngineering($message);

if ($warning !== false) {
$prefix = '<p class="bg-danger">' . $warning . '</p> ';
} else {
$prefix = '';
}

self::$db->query(
'INSERT INTO sis2.messages (timeslotid, commtypeid, sender, subject, content, statusid, comm_source)
VALUES ($1, $2, $3, $4, $5, $6, $7)',
[
$this->getID(), // timeslot
6, // commtypeid : website
$sender, // sender
substr($message, 0, 144), // subject : trancated message
$prefix . $message, // content : message with prefix
$junk ? 4 : 1, // statusid : junk or unread
$number, // comm_source : sender mobile number
// TODO: ^ maybe not (GDPR)
]
);

return $this;
}

/**
* Signs the given user into the timeslot to say they were
* on air at this time, if they haven't been signed in already.
Expand Down
63 changes: 63 additions & 0 deletions src/Controllers/SIS/whatsapp.incoming.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

use MyRadio\Config;
use MyRadio\MyRadioException;
use MyRadio\ServiceAPI\MyRadio_Timeslot;

if (!Config::$sis_whatsapp_enable) {
throw new MyRadioException('SIS Whatsapp is disabled', 404);
}

if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if (!array_key_exists('hub_mode', $_GET) || !array_key_exists('hub_challenge', $_GET) || !array_key_exists('hub_verify_token', $_GET)) {
error_log('missing get parameter');
throw new MyRadioException('Missing get parameters', 400);
}
$hub_mode = $_GET['hub_mode'];
$hub_challenge = $_GET['hub_challenge'];
$hub_verify_token = $_GET['hub_verify_token'];
if ($hub_mode !== 'subscribe') {
error_log('wrong hub mode');
throw new MyRadioException('Incorrect mode', 400);
}
if ($hub_verify_token !== Config::$sis_whatsapp_verify_token) {
error_log('incorrect verify token');
throw new MyRadioException('Incorrect verify token', 400);
}
header('Content-Type: text/plain');
echo $hub_challenge;
} else if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'application/json') !== false) {
$raw = file_get_contents('php://input') ?: '';
$data = json_decode($raw, true) ?: [];
} else {
$data = $_REQUEST;
}

$timeslot = MyRadio_Timeslot::getCurrentTimeslot();
if ($timeslot !== null) {
foreach ($data['entry'] as $entry) {
foreach ($entry['changes'] as $change) {
$contacts = $change['value']['contacts'];
$messages = $change['value']['messages'];
foreach ($messages as $message) {
$from = $message['from'];
$from_name = 'Unknown';
foreach ($contacts as $contact) {
if ($contact['wa_id'] === $from) {
$from_name = $contact['profile']['name'];
}
}
$type = $message['type'];
$body = '';
if (array_key_exists('text', $message)) {
$body = $message['text']['body'];
}
if ($body !== '') {
$timeslot->sendWhatsappMessage($body, $from_name, $from);
}
}
}
}
}
}
2 changes: 1 addition & 1 deletion src/Controllers/root.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* This number is incremented every time a database patch is released.
* Patches are scripts in schema/patches.
*/
define('MYRADIO_CURRENT_SCHEMA_VERSION', 18);
define('MYRADIO_CURRENT_SCHEMA_VERSION', 19);

/*
* Turn on Error Reporting for the start. Once the Config object is loaded
Expand Down
10 changes: 7 additions & 3 deletions src/Public/js/sis.messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
var Messages = function () {
var highest_message_id = 0,
unreadMessages = 0,
glyphicons = ["question-sign", "envelope", "phone", "globe"],
locationNames = ["unknown method", "email", "text message", "the website"],
glyphicons = ["question-sign", "envelope", "phone", "globe", "globe", "globe", "phone"],
locationNames = ["unknown method", "email", "text message", "the website", "request", "mobile site", "WhatsApp"],
table = document.createElement("table"),
clickHandler = function (context, row, message) {
$(row).click(function () {
Expand All @@ -30,7 +30,11 @@ var Messages = function () {
location = location + " (" + message.location[1] + ")";
}
}
myradio.createDialog("Message", "<blockquote><p>" +message.body + "</p><footer>Listener via " + locationName + " at <cite>" + time + "</cite>.</footer></blockquote>" + location);
var listener = 'Listener';
if (message.type === 6) {
listener = message.sender;
}
myradio.createDialog("Message", "<blockquote><p>" +message.body + "</p><footer>" + listener + " via " + locationName + " at <cite>" + time + "</cite>.</footer></blockquote>" + location);
});
};

Expand Down