diff --git a/api/cora/setting.example.php b/api/cora/setting.example.php
index cd89d72..b898295 100644
--- a/api/cora/setting.example.php
+++ b/api/cora/setting.example.php
@@ -111,19 +111,26 @@ final class setting {
'beestat_root_uri' => '',
/**
- * Your Mailchimp API Key; provided to you when you create a Mailchimp
- * developer account.
+ * Your Mailgun API Key.
*
- * Example: hcU74TJgGS5k7vuw3NSzkRMSWNPkv8Af-us18
+ * Example: 4b34e48e768fa45c4a6ac65dd4cf1da9-7e28d3c3-61713777
*/
- 'mailchimp_api_key' => '',
+ 'mailgun_api_key' => '',
/**
- * ID of the mailing list to send emails to.
+ * API base URL including the sending domain. Make sure to include the
+ * trailing slash.
*
- * Example: uw3NSzkRMS
+ * Example: https://api.mailgun.net/v3/
*/
- 'mailchimp_list_id' => '',
+ 'mailgun_base_url' => '',
+
+ /**
+ * The specific newsletter to subscribe users to.
+ *
+ * Example: newsletter@app.beestat.io
+ */
+ 'mailgun_newsletter' => '',
/**
* Auth ID for Smarty Streets address verification.
diff --git a/api/ecobee.php b/api/ecobee.php
index 53fcb87..c757838 100644
--- a/api/ecobee.php
+++ b/api/ecobee.php
@@ -60,13 +60,9 @@ class ecobee extends external_api {
);
$identifiers = [];
- $email_addresses = [];
foreach($response['thermostatList'] as $thermostat) {
$runtime = $thermostat['runtime'];
$identifiers[] = $thermostat['identifier'];
-
- $notification_settings = $thermostat['notificationSettings'];
- $email_addresses = array_merge($email_addresses, $notification_settings['emailAddresses']);
}
// Look to see if any of the returned thermostats exist. This does not use
@@ -119,22 +115,6 @@ class ecobee extends external_api {
else {
$this->api('user', 'create_anonymous_user');
$this->api('ecobee_token', 'create', ['attributes' => $ecobee_token]);
-
- if(count($email_addresses) > 0) {
- try {
- $this->api(
- 'mailchimp',
- 'subscribe',
- [
- 'email_address' => $email_addresses[0]
- ]
- );
- } catch(Exception $e) {
- // Ignore failed subscribe exceptions since it's not critical to the
- // success of this. Everything is logged regardless.
- }
- }
-
}
// Redirect to the proper location.
diff --git a/api/ecobee_thermostat.php b/api/ecobee_thermostat.php
index 38e5bae..5c8ebe6 100644
--- a/api/ecobee_thermostat.php
+++ b/api/ecobee_thermostat.php
@@ -99,6 +99,7 @@ class ecobee_thermostat extends cora\crud {
// Loop over the returned thermostats and create/update them as necessary.
$thermostat_ids_to_keep = [];
+ $email_addresses = [];
foreach($response['thermostatList'] as $api_thermostat) {
$ecobee_thermostat = $this->get(
[
@@ -169,6 +170,12 @@ class ecobee_thermostat extends cora\crud {
]
);
+ foreach($api_thermostat['notificationSettings']['emailAddresses'] as $email_address) {
+ if(preg_match('/.+@.+\..+/', $email_address) === 1) {
+ $email_addresses[] = trim(strtolower($email_address));
+ }
+ }
+
// Grab a bunch of attributes from the ecobee_thermostat and attach them
// to the thermostat.
$attributes = [];
@@ -260,6 +267,19 @@ class ecobee_thermostat extends cora\crud {
);
}
+ // Update the email_address on the user.
+ if(count($email_addresses) > 0) {
+ $email_address_counts = array_count_values($email_addresses);
+ arsort($email_address_counts);
+ $email_address = array_keys(array_slice($email_address_counts, 0, 1, true))[0];
+ $this->api('user', 'update', [
+ 'attributes' => [
+ 'user_id' => $this->session->get_user_id(),
+ 'email_address' => $email_address
+ ]
+ ]);
+ }
+
// Inactivate any ecobee_thermostats that were no longer returned.
$thermostats = $this->api('thermostat', 'read');
$ecobee_thermostat_ids_to_return = [];
diff --git a/api/external_api.php b/api/external_api.php
index 748d0c3..6b1a2c9 100644
--- a/api/external_api.php
+++ b/api/external_api.php
@@ -1,7 +1,7 @@
curl_info = curl_getinfo($curl_handle);
- if($curl_response === false || curl_errno($curl_handle) !== 0) {
+ if(
+ $curl_response === false ||
+ curl_errno($curl_handle) !== 0
+ ) {
// Error logging
if($this::$log_mysql === 'all' || $this::$log_mysql === 'error') {
$this->log_mysql($curl_response, true);
@@ -103,7 +106,6 @@ class external_api extends cora\api {
'curl_error' => curl_error($curl_handle)
]
);
-
}
// General (success) logging
diff --git a/api/mailchimp.php b/api/mailchimp.php
deleted file mode 100644
index dd44dfa..0000000
--- a/api/mailchimp.php
+++ /dev/null
@@ -1,80 +0,0 @@
-curl([
- 'url' => 'https://us18.api.mailchimp.com/3.0/' . $endpoint,
- 'post_fields' => json_encode($data, JSON_FORCE_OBJECT),
- 'method' => $method,
- 'header' => [
- 'Authorization: Basic ' . base64_encode(':' . $this->setting->get('mailchimp_api_key')),
- 'Content-Type: application/x-www-form-urlencoded'
- ]
- ]);
-
- $response = json_decode($curl_response, true);
-
- if ($response === null) {
- throw new Exception('Invalid JSON');
- }
-
- return $response;
- }
-
- /**
- * Subscribe an email address to the mailing list. This will only mark you
- * as "pending" so you have to click a link in the email to actually
- * subscribe.
- *
- * @param string $email_address The email address to subscribe.
- *
- * @throws Exception If subscribing to the mailing list fails for some
- * reason. For example, if already subscribed.
- *
- * @return array The MailChimp response.
- */
- public function subscribe($email_address) {
- $method = 'POST';
-
- $endpoint =
- 'lists/' .
- $this->setting->get('mailchimp_list_id') .
- '/members/'
- ;
-
- $data = [
- 'email_address' => $email_address,
- 'status' => 'pending'
- ];
-
- $response = $this->mailchimp_api($method, $endpoint, $data);
-
- if(isset($response['id']) === false) {
- throw new Exception('Could not subscribe to mailing list.');
- }
-
- return $response;
- }
-}
diff --git a/api/mailgun.php b/api/mailgun.php
new file mode 100644
index 0000000..768a4ce
--- /dev/null
+++ b/api/mailgun.php
@@ -0,0 +1,123 @@
+ [],
+ 'public' => [
+ 'subscribe',
+ 'unsubscribe'
+ ]
+ ];
+
+ /**
+ * Send an API call off to mailgun
+ *
+ * @param string $method HTTP Method.
+ * @param string $endpoint API Endpoint.
+ * @param array $data API request data.
+ *
+ * @throws Exception If mailgun did not return valid JSON.
+ *
+ * @return array The mailgun response.
+ */
+ private function mailgun_api($method, $endpoint, $data) {
+ $curl_response = $this->curl([
+ 'url' => $this->setting->get('mailgun_base_url') . $endpoint,
+ 'post_fields' => $data,
+ 'method' => $method,
+ 'header' => [
+ 'Authorization: Basic ' . base64_encode('api:' . $this->setting->get('mailgun_api_key')),
+ 'Content-Type: multipart/form-data'
+ ]
+ ]);
+
+ $response = json_decode($curl_response, true);
+
+ if ($response === null) {
+ throw new cora\exception('Invalid JSON', 10600);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Subscribe to the mailing list.
+ *
+ * @param string $email_address The email address to subscribe.
+ *
+ * @throws exception If the subscribe failed.
+ *
+ * @return array Subscriber info.
+ */
+ public function subscribe($email_address) {
+ $method = 'POST';
+
+ $endpoint = 'lists/' . $this->setting->get('mailgun_newsletter') . '/members';
+
+ $data = [
+ 'address' => $email_address,
+ 'subscribed' => 'yes',
+ 'upsert' => 'yes'
+ ];
+
+ $response = $this->mailgun_api($method, $endpoint, $data);
+
+ if (
+ isset($response['member']) &&
+ isset($response['member']['address']) &&
+ isset($response['member']['subscribed']) &&
+ $response['member']['address'] === $email_address &&
+ $response['member']['subscribed'] === true
+ ) {
+ return $response['member'];
+ } else {
+ throw new cora\exception('Failed to subscribe.', 10601);
+ }
+ }
+
+ /**
+ * Unsubscribe from the mailing list.
+ *
+ * @param string $email_address The email address to unsubscribe.
+ *
+ * @throws exception If the unsubscribe failed.
+ *
+ * @return array Subscriber info.
+ */
+ public function unsubscribe($email_address) {
+ $method = 'POST';
+
+ $endpoint = 'lists/' . $this->setting->get('mailgun_newsletter') . '/members';
+
+ $data = [
+ 'address' => $email_address,
+ 'subscribed' => 'no',
+ 'upsert' => 'yes'
+ ];
+
+ $response = $this->mailgun_api($method, $endpoint, $data);
+
+ if (
+ isset($response['member']) &&
+ isset($response['member']['address']) &&
+ isset($response['member']['subscribed']) &&
+ $response['member']['address'] === $email_address &&
+ $response['member']['subscribed'] === false
+ ) {
+ return $response['member'];
+ } else {
+ throw new cora\exception('Failed to unsubscribe.', 10602);
+ }
+ }
+}
diff --git a/api/mailchimp_api_cache.php b/api/mailgun_api_cache.php
similarity index 55%
rename from api/mailchimp_api_cache.php
rename to api/mailgun_api_cache.php
index 35f5d28..7d7ac7f 100644
--- a/api/mailchimp_api_cache.php
+++ b/api/mailgun_api_cache.php
@@ -1,8 +1,8 @@
-get('environment') === 'dev' || $setting->get('environment') === 'd
echo '' . PHP_EOL;
echo '' . PHP_EOL;
echo '' . PHP_EOL;
+ echo '' . PHP_EOL;
echo '' . PHP_EOL;
echo '' . PHP_EOL;
echo '' . PHP_EOL;
diff --git a/js/layer/load.js b/js/layer/load.js
index 5f695f0..2986ba5 100644
--- a/js/layer/load.js
+++ b/js/layer/load.js
@@ -225,7 +225,14 @@ beestat.layer.load.prototype.decorate_ = function(parent) {
}
}
- if (
+ /*
+ * Show the first run modal or the announcements modal if there are unread
+ * important announcements.
+ */
+ if (beestat.setting('first_run') === true) {
+ beestat.setting('first_run', false);
+ (new beestat.component.modal.newsletter()).render();
+ } else if (
last_read_announcement_id === undefined ||
(
most_recent_important_announcement_id !== undefined &&
@@ -234,7 +241,6 @@ beestat.layer.load.prototype.decorate_ = function(parent) {
) {
(new beestat.component.modal.announcements()).render();
}
-
});
api.send();