event's API support update and image_url

This commit is contained in:
les 2020-05-14 22:36:58 +02:00
parent 34395c3d66
commit 22381d1fe6
7 changed files with 300 additions and 232 deletions

View file

@ -236,6 +236,8 @@ const eventController = {
if (req.file) { if (req.file) {
eventDetails.image_path = req.file.filename eventDetails.image_path = req.file.filename
} else if (body.image_url) {
eventDetails.image_path = await helpers.getImageFromURL(body.image_url)
} }
const event = await Event.create(eventDetails) const event = await Event.create(eventDetails)
@ -289,6 +291,7 @@ const eventController = {
} }
const body = req.body const body = req.body
const event = await Event.findByPk(body.id) const event = await Event.findByPk(body.id)
if (!event) return res.sendStatus(404)
if (!req.user.is_admin && event.userId !== req.user.id) { if (!req.user.is_admin && event.userId !== req.user.id) {
return res.sendStatus(403) return res.sendStatus(403)
} }
@ -316,6 +319,8 @@ const eventController = {
} }
} }
eventDetails.image_path = req.file.filename eventDetails.image_path = req.file.filename
} else if (body.image_url) {
eventDetails.image_path = await helpers.getImageFromURL(body.image_url)
} }
await event.update(eventDetails) await event.update(eventDetails)

View file

@ -86,8 +86,7 @@ api.put('/place', isAdmin, eventController.updatePlace)
* @param {array} [recurrent.days] - array of days * @param {array} [recurrent.days] - array of days
* @param {image} [image] - Image * @param {image} [image] - Image
*/ */
api.post('/event', upload.single('image'), eventController.add) api.post('/event', hasPerm('event:write'), upload.single('image'), eventController.add)
api.put('/event', hasPerm('event:write'), upload.single('image'), eventController.update) api.put('/event', hasPerm('event:write'), upload.single('image'), eventController.update)
// remove event // remove event

View file

@ -45,7 +45,7 @@ const DiskStorage = {
.pipe(outStream) .pipe(outStream)
.on('error', err) .on('error', err)
outStream.on('finish', function () { outStream.on('finish', () => {
cb(null, { cb(null, {
destination: config.upload_path, destination: config.upload_path,
filename, filename,

View file

@ -2,7 +2,13 @@ const settingsController = require('./api/controller/settings')
const acceptLanguage = require('accept-language') const acceptLanguage = require('accept-language')
const moment = require('moment-timezone') const moment = require('moment-timezone')
const config = require('config') const config = require('config')
const debug = require('debug')('helpers')
const pkg = require('../package.json') const pkg = require('../package.json')
const fs = require('fs')
const path = require('path')
const sharp = require('sharp')
const axios = require('axios')
const crypto = require('crypto')
const DOMPurify = require('dompurify') const DOMPurify = require('dompurify')
const { JSDOM } = require('jsdom') const { JSDOM } = require('jsdom')
@ -59,6 +65,45 @@ module.exports = {
moment.locale(req.settings.locale) moment.locale(req.settings.locale)
moment.tz.setDefault(req.settings.instance_timezone) moment.tz.setDefault(req.settings.instance_timezone)
next() next()
},
async getImageFromURL (url) {
debug(`getImageFromURL ${url}`)
const filename = crypto.randomBytes(16).toString('hex') + '.webp'
const finalPath = path.resolve(config.upload_path, filename)
const thumbPath = path.resolve(config.upload_path, 'thumb', filename)
const outStream = fs.createWriteStream(finalPath)
const thumbStream = fs.createWriteStream(thumbPath)
const resizer = sharp().resize(1200).webp({ quality: 95 })
const thumbnailer = sharp().resize(400).webp({ quality: 90 })
const response = await axios({ method: 'GET', url, responseType: 'stream' })
return new Promise((resolve, reject) => {
let onError = false
const err = e => {
if (onError) {
return
}
onError = true
reject(e)
}
response.data
.pipe(thumbnailer)
.on('error', err)
.pipe(thumbStream)
.on('error', err)
response.data
.pipe(resizer)
.on('error', err)
.pipe(outStream)
.on('error', err)
outStream.on('finish', () => resolve(filename))
})
} }
} }

View file

@ -2,244 +2,41 @@
/* /*
Plugin Name: WPGancio Plugin Name: WPGancio
Plugin URI: https://gancio.org Plugin URI: https://gancio.org
Description: Description: Connects an user of a gancio instance to a Wordpress user so that published events are automatically pushed with Gancio API.
Version: 1.0 Version: 1.0
Author: Author: Gancio
Author URI: https://gancio.org Author URI: https://gancio.org
License: GPL2 License: AGPL 3.0
License URI: https://
Copyright YEAR PLUGIN_AUTHOR_NAME (email : your email address) WPGancio is free software: you can redistribute it and/or modify it under the
(Plugin Name) is free software: you can redistribute it and/or modify terms of the GNU Affero General Public License as published by the Free
it under the terms of the GNU General Public License as published by Software Foundation, either version 3 of the license, or any later version.
the Free Software Foundation, either version 2 of the License, or
any later version.
(Plugin Name) is distributed in the hope that it will be useful, WPGancio is distributed in the hope that it will be useful, but WITHOUT ANY
but WITHOUT ANY WARRANTY; without even the implied warranty of WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the PARTICULAR PURPOSE. See the GNU General Public License for more details.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU Affero General Public License
along with (WPGancio). If not, see (http://link to your plugin license). along with (WPGancio). If not, see (https://www.gnu.org/licenses/agpl-3.0.html).
*/ */
defined( 'ABSPATH' ) or die( 'Nope, not accessing this' ); defined( 'ABSPATH' ) or die( 'Nope, not accessing this' );
require_once('settings.php');
require_once('oauth.php');
/** /**
* @internal never define functions inside callbacks. * What does WPGancio do?
* these functions could be run multiple times; this would result in a fatal error. * This plugin connects a user of a gancio instance to a Wordpress user so that events published
* on Wordpress are automatically inserted.
* It requires an event manager plugin, only Event Organiser (https://wp-event-organiser.com/) is
* supported until now but to add another plugin it's easy.
*/ */
/** /**
* custom option and settings * - Add Gancio Settings page to select an instance URL and...
*/ * - start an OAuth 2.0 authentication flow with the selected instance
function wpgancio_settings_init() { * - Send each new / updated events to the selected instance via Gancio API
// register a new setting for "wpgancio" page
register_setting( 'wpgancio', 'wpgancio_options' );
// register a new section in the "wpgancio" page
add_settings_section(
'wpgancio_section_developers',
__( 'Gancio settings.', 'wpgancio' ),
'wpgancio_section_developers_cb',
'wpgancio');
// register a new field in the "wporg_section_developers" section, inside the "wporg" page
add_settings_field(
'wpgancio_field_url', // as of WP 4.6 this value is used only internally
// use $args' label_for to populate the id inside the callback
__( 'Instance URL', 'wpgancio' ),
'wpgancio_field_url_cb',
'wpgancio',
'wpgancio_section_developers',
[
'label_for' => 'wpgancio_field_url',
'class' => 'wpgancio_row',
'wpgancio_custom_data' => 'custom',
]
);
}
/**
* register our wpgancio_settings_init to the admin_init action hook
*/
add_action( 'admin_init', 'wpgancio_settings_init' );
add_action( 'update_option_wpgancio_options', 'wpgancio_update_options', 15, 2);
function wpgancio_update_options ($old_value, $new_value) {
$instance_url = $new_value['wpgancio_field_url'];
$redirect_uri = get_site_url(null, '/wp-admin/options-general.php?page=wpgancio' );
// wp_redirect(get_option('wpgancio_field_url'));
$response = wp_remote_post( "$instance_url/api/client", array(
'method' => 'POST',
'body' => array(
'client_name' => 'WPGancio',
'redirect_uris' => $redirect_uri,
'scopes' => 'event:write',
'website' => 'https://gancio.org'
)
));
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
echo "Something went wrong: $error_message";
exit;
}
$data = json_decode( wp_remote_retrieve_body($response), true);
// var_dump($data);
update_option('wpgancio_client_secret', $data['client_secret']);
update_option('wpgancio_client_id', $data['client_id']);
wp_redirect($instance_url . "/authorize?response_type=code&redirect_uri=$redirect_uri&scope=event:write&client_id=" . get_option('wpgancio_client_id'));
exit;
};
function wpgancio_update_event ($post_id) {
$event = get_post( $post_id );
$date = eo_get_schedule_start( 'U', $post_id );
$venue_id = eo_get_venue($post_id);
$place_name = eo_get_venue_name($venue_id);
$place_address = eo_get_venue_address($venue_id);
$options = get_option( 'wpgancio_options' );
$instance_url = $options['wpgancio_field_url'];
$response = wp_remote_post($instance_url . '/api/event', array(
'headers' => array (
'Authorization' => 'Bearer ' . get_option('wpgancio_token')
),
'body' => array(
'title' => $event->post_title,
'description' => $event->post_content,
'start_datetime' => intval($date),
'place_name' => $place_name,
'place_address' => $place_address
)
));
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
echo "Something went wrong: $error_message";
exit;
}
var_dump($response);
$data = wp_remote_retrieve_body($response);
// syslog(1, "sono qua!");
}
add_action('eventorganiser_save_event', 'wpgancio_update_event', 15);
/**
* custom option and settings:
* callback functions
*/ */
// developers section cb
// section callbacks can accept an $args parameter, which is an array.
// $args have the following keys defined: title, id, callback.
// the values are defined at the add_settings_section() function.
function wpgancio_section_developers_cb( $args ) {
?>
<p id="<?php echo esc_attr( $args['id'] ); ?>"><?php esc_html_e( 'Follow the white rabbit.', 'wporg' ); ?></p>
<?php
}
// instance url field cb
// field callbacks can accept an $args parameter, which is an array.
// $args is defined at the add_settings_field() function.
// wordpress has magic interaction with the following keys: label_for, class.
// the "label_for" key value is used for the "for" attribute of the <label>.
// the "class" key value is used for the "class" attribute of the <tr> containing the field.
// you can add custom key value pairs to be used inside your callbacks.
function wpgancio_field_url_cb( $args ) {
// get the value of the setting we've registered with register_setting()
$options = get_option( 'wpgancio_options' );
// output the field
?>
<input id="<?php echo esc_attr( $args['label_for'] ); ?>" value="<?php echo $options[ $args['label_for'] ]; ?>"
data-custom="<?php echo esc_attr( $args['wpgancio_custom_data'] ); ?>"
name="wpgancio_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
>
<p class="description">
<?php esc_html_e( 'Insert your gancio instance URL', 'wpgancio' ); ?>
</p>
<?php
}
function wpgancio_options_page() {
// add top level menu page
add_options_page(
'Gancio',
'Gancio',
'manage_options',
'wpgancio',
'wpgancio_options_page_html'
);
}
/**
* register our wporg_options_page to the admin_menu action hook
*/
add_action( 'admin_menu', 'wpgancio_options_page' );
/**
* top level menu:
* callback functions
*/
function wpgancio_options_page_html() {
$code = $_GET['code'];
if ( $code ) {
update_option('wpgancio_code', $code);
$options = get_option( 'wpgancio_options' );
$instance_url = $options['wpgancio_field_url'];
$response = wp_remote_post($instance_url . "/oauth/token", array(
'body' => array(
'client_id' => get_option('wpgancio_client_id'),
'client_secret' => get_option('wpgancio_client_secret'),
'scope' => 'event:write',
'grant_type' => 'authorization_code',
'code' => $code,
'state' => 'antani'
)));
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
echo "Something went wrong: $error_message";
exit;
}
$data = json_decode( wp_remote_retrieve_body($response), true);
update_option('wpgancio_token', $data['access_token']);
update_option('wpgancio_refresh', $data['refresh_token']);
}
// check user capabilities
if ( ! current_user_can( 'manage_options' ) ) { return; }
// add error/update messages
// check if the user have submitted the settings
// wordpress will add the "settings-updated" $_GET parameter to the url
if ( isset( $_GET['settings-updated'] ) ) {
// add settings saved message with the class of "updated"
add_settings_error( 'wpgancio_messages', 'wpgancio_message', __( 'Settings Saved', 'wpgancio' ), 'updated' );
}
// show error/update messages
settings_errors( 'wpgancio_messages' );
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<form action="options.php" method="post">
<?php
// output security fields for the registered setting "wpgancio"
settings_fields( 'wpgancio' );
// output setting sections and their fields
// (sections are registered for "wpgancio", each field is registered to a specific section)
do_settings_sections( 'wpgancio' );
// output save settings button
submit_button( 'Save Settings' );
?>
</form>
</div>
<?php
}

66
wp-plugin/oauth.php Normal file
View file

@ -0,0 +1,66 @@
<?php
defined( 'ABSPATH' ) or die( 'Nope, not accessing this' );
// eventorganizer / triggered after an event has been updated
// http://codex.wp-event-organiser.com/hook-eventorganiser_save_event.html
add_action('eventorganiser_save_event', 'wpgancio_save_event', 15);
function wpgancio_save_event ($post_id) {
$event = get_post( $post_id );
// do not save if it's a draft
if ($event->post_status != 'publish') {
return;
}
$gancio_id = get_post_meta($post_id, 'gancio_id', TRUE);
// image_path
$date = eo_get_schedule_start( 'U', $post_id );
// get place details
$venue_id = eo_get_venue($post_id);
$place_name = eo_get_venue_name($venue_id);
$place_address = eo_get_venue_address($venue_id);
$options = get_option('wpgancio_options');
$instance_url = $options['wpgancio_field_url'];
$body = array (
'title' => $event->post_title,
'description' => $event->post_content,
'start_datetime' => intval($date),
'place_name' => $place_name,
'place_address' => $place_address,
);
// add image if specified
$image_url = get_the_post_thumbnail_url($post_id);
if ($image_url) {
$body['image_url'] = $image_url;
}
// update
if ($gancio_id) {
$body['id'] = $gancio_id;
$http = _wp_http_get_object();
$response = $http->request( $instance_url . '/api/event', array(
'method' => 'PUT',
'headers' => array (
'Authorization' => 'Bearer ' . get_option('wpgancio_token')
), 'body' => $body ));
} else { // or create
$response = wp_remote_post($instance_url . '/api/event', array(
'headers' => array (
'Authorization' => 'Bearer ' . get_option('wpgancio_token')
), 'body' => $body ));
}
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
echo "<div class='error notice'><p>${error_message}</p></div>";
return;
}
$data = json_decode(wp_remote_retrieve_body($response));
update_post_meta($post_id, 'gancio_id', $data->id);
}

156
wp-plugin/settings.php Normal file
View file

@ -0,0 +1,156 @@
<?php
defined( 'ABSPATH' ) or die( 'Nope, not accessing this' );
// Fires as an admin screen or script is being initialized. Register out settings
add_action( 'admin_init', 'wpgancio_settings_init' );
function wpgancio_settings_init() {
register_setting( 'wpgancio', 'wpgancio_options' );
// register a new settings page
add_settings_section('wpgancio_settings', __('Settings'), FALSE, 'wpgancio');
// register a new field in the 'wpgancio_settings' section
add_settings_field('wpgancio_field_url', __( 'Instance URL', 'wpgancio' ),
'wpgancio_field_url_cb', 'wpgancio',
'wpgancio_settings', [ 'label_for' => 'wpgancio_field_url' ] );
}
add_action( 'update_option_wpgancio_options', 'wpgancio_update_options', 15, 2);
// Fires before the administration menu loads in the admin, add our options page
add_action( 'admin_menu', 'wpgancio_options_page' );
function wpgancio_update_options ($old_value, $new_value) {
$instance_url = $new_value['wpgancio_field_url'];
$redirect_uri = get_site_url(null, '/wp-admin/options-general.php?page=wpgancio' );
// create this WP instance as a new client in selected gancio instance
$response = wp_remote_post( "$instance_url/api/client", array(
'method' => 'POST',
'body' => array(
'client_name' => 'WPGancio',
'redirect_uris' => esc_html($redirect_uri),
'scopes' => 'event:write',
'website' => 'https://gancio.org'
)
));
if ( is_wp_error( $response ) ) {
add_settings_error('wpgancio_messages', 'wpgancio_messages',
$response->get_error_message());
} else {
$data = json_decode( wp_remote_retrieve_body($response), true);
update_option('wpgancio_client_secret', $data['client_secret']);
update_option('wpgancio_client_id', $data['client_id']);
$query = join('&', array(
'response_type=code',
'redirect_uri=' . esc_html($redirect_uri),
'scope=event:write',
'client_id=' . get_option('wpgancio_client_id'),
'state=antani'
));
wp_redirect("${instance_url}/authorize?${query}");
exit;
}
};
function wpgancio_options_page() {
// add top level menu page
add_options_page(
'Gancio',
'Gancio',
'manage_options',
'wpgancio',
'wpgancio_options_page_html'
);
}
// instance url field cb
// field callbacks can accept an $args parameter, which is an array.
// $args is defined at the add_settings_field() function.
// wordpress has magic interaction with the following keys: label_for, class.
// the "label_for" key value is used for the "for" attribute of the <label>.
// the "class" key value is used for the "class" attribute of the <tr> containing the field.
// you can add custom key value pairs to be used inside your callbacks.
function wpgancio_field_url_cb( $args ) {
// get the value of the setting we've registered with register_setting()
$options = get_option( 'wpgancio_options' );
// output the field
?>
<input id="<?php echo esc_attr( $args['label_for'] ); ?>"
value="<?php echo $options[ $args['label_for'] ]; ?>"
name="wpgancio_options[<?php echo esc_attr( $args['label_for'] ); ?>]">
<p class="description">
<?php esc_html_e( 'Insert your gancio instance URL', 'wpgancio' ); ?>
</p>
<?php
}
/**
* top level menu:
* callback functions
*/
function wpgancio_options_page_html() {
// check user capabilities
if ( ! current_user_can( 'manage_options' ) ) { return; }
// show error/update messages
//settings_errors( 'wpgancio_messages' );
$code = $_GET['code'];
if ( $code ) {
update_option('wpgancio_code', $code);
$options = get_option( 'wpgancio_options' );
$instance_url = $options['wpgancio_field_url'];
$response = wp_remote_post($instance_url . "/oauth/token", array(
'body' => array(
'client_id' => get_option('wpgancio_client_id'),
'client_secret' => get_option('wpgancio_client_secret'),
'scope' => 'event:write',
'grant_type' => 'authorization_code',
'code' => $code,
'state' => 'antani'
)));
if ( is_wp_error( $response ) ) {
add_settings_error('wpgancio_messages', 'wpgancio_messages', $response->get_error_message());
settings_errors( 'wpgancio_messages' );
} else if ( $response['response']['code'] == 500 ) {
add_settings_error('wpgancio_messages', 'wpgancio_messages', wp_remote_retrieve_body($response));
settings_errors( 'wpgancio_messages' );
} else {
$data = json_decode( wp_remote_retrieve_body($response), true);
update_option('wpgancio_token', $data['access_token']);
update_option('wpgancio_refresh', $data['refresh_token']);
add_settings_error('wpgancio_messages', 'wpgancio_messages', 'TUTTO REGO MATCH!', 'success');
settings_errors( 'wpgancio_messages' );
}
}
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<form action="options.php" method="post">
<?php
// output security fields for the registered setting "wpgancio"
settings_fields( 'wpgancio' );
// output setting sections and their fields
// (sections are registered for "wpgancio", each field is registered to a specific section)
do_settings_sections( 'wpgancio' );
// output save settings button
submit_button( 'Save Settings' );
?>
</form>
</div>
<?php
}