How can i use login_url in inline_keyboard Telegram bot php - telegram

I have
$inline_button1 = array("text"=>"Text","login_url"=>array("url" => "https://example.com"));
$inline_keyboard = [[$inline_button1]];
$keyboard=array("inline_keyboard"=>$inline_keyboard);
$replyMarkup = json_encode($keyboard);
$tg->send2($id, 'Test', $replyMarkup);
Function send2 look as
public function send2($id, $message, $reply) {
$data = array(
'chat_id' => $id,
'text' => $message,
'reply_markup' => $reply,
'parse_mode' => 'html',
);
$out = $this->request('sendMessage', $data);
return $out;
}
If i use 'url' instead 'login_url' it works fine.

I find the problem, it was needed specify parameter DOMAIN in botfather setting

Related

Custom post type API custom endpoint for single post by ID

I've created a WordPress custom post type, then I've created REST API custom endpoint to GET all the posts works ok. Then I've created another custom endpoint to GET single post by ID. For example http://localhost:8888/wordpress/wp-json/lc/v1/cars/120
I have created a few posts, each time I change the ID at the end of the route to 118 or 116 it shows the same data for the latest post-ID 120. I need the relevant data to show based on the post ID, I would appreciate any kind of help. Thanks
public function rest_posts_endpoints(){
register_rest_route(
'lc/v1',
'/cars/(?P<id>\d+)',
[
'method' => 'GET',
'callback' => [$this, 'rest_endpoint_handler_single'],
]
);
}
public function rest_endpoint_handler_single( WP_REST_Request $request ) {
$params = $request->get_query_params();
$args = [
'post_type' => 'cars',
'id' => $params['id'],
];
$post = get_posts($args);
$data['id'] = $post[0]->ID;
$data['slug'] = $post[0]->post_name;
$data['title'] = $post[0]->post_title;
$data['content'] = $post[0]->post_content;
$data['excerpt'] = $post[0]->post_excerpt;
return $data;
}
public function rest_endpoint_handler_single( WP_REST_Request $request ) {
$params = $request->get_params();
$args = [
'post_type' => 'cars',
'id' => $params['id'],
'include' => array($params['id']),
];
$post = get_posts($args);
$data['id'] = $post[0]->ID;
$data['slug'] = $post[0]->post_name;
$data['title'] = $post[0]->post_title;
$data['content'] = $post[0]->post_content;
$data['excerpt'] = $post[0]->post_excerpt;
return $data;
}

Add links on Wordpress custom endpoint

I created a custom endpoint for specific data from a custom table in my Wordpress plugin. It get's all the data from the table with the getHelpers() function. After that it will be merged by some user data. I would like to add the profile_image as a link to the response so we can get it with the embed parameter.
What is the best way to add the link to the response? I know the $response->add_link() function but this would add it to the response and not to each contributor.
I tried to add the link as an array but this won't react on the _embed parameter.
This is my code for the custom endpoint:
class VEMS_Rest_Contributors extends WP_REST_Controller {
protected $namespace = 'vems/v2';
protected $rest_base = 'contributors';
/**
* Register the routes for coupons.
*/
public function register_routes() {
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'args' => $this->get_collection_params(),
) );
}
public function get_items( WP_REST_Request $request ) {
$project_id = $request->get_param( 'project_id' );
$contributors = array();
if( !empty($project_id) ) {
$project = new VEMS_Project( $request['project_id'] );
$helpers = $project->getHelpers();
foreach($helpers as $helper) {
$contributor = array();
if( !empty($helper->contributor_id) ) {
$user = get_user_by( 'ID', $helper->contributor_id );
$user_meta = get_user_meta( $helper->contributor_id );
$contributor['ID'] = $helper->contributor_id;
$contributor['user_nicename'] = $user->data->display_name;
$contributor['user_profile_image'] = $user_meta['contributor_profile_image'][0];
} else {
$contributor['user_nicename'] = $helper->name;
$contributor['user_profile_image'] = $helper->image_id;
}
$contributor['item_total'] = $helper->item_total;
$contributor['checked'] = $helper->checked;
$contributor['helper_date'] = $helper->helper_date;
/*
$contributor['_links']['profile_image'] = array(
'href' => rest_url( '/wp/v2/media/' . $contributor['user_profile_image'] ),
'embeddable' => true
);
*/
$contributors[] = $contributor;
}
}
$response = rest_ensure_response( $contributors );
return $response;
}
public function get_collection_params() {
$params['project_id'] = array(
'description' => __( 'Limit result set to contributors assigned a specific project.', 'vems' ),
'type' => 'integer',
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
);
return $params;
}
}
to handle links on route vems/v2/contributors?_embed, the element profile_image must be an array of links and then you can do that
$contributor['_links']['profile_image'] = [
[
'href' => rest_url( '/wp/v2/media/' . $contributor['ID'] ),
'embeddable' => true,
],
];

Wp Rest Api Custom End point POST request

Im trying to post some data to custom api endpoint that i created,
This is what my wordpress custom endpoint code.
register_rest_route( 'api/v1', '/cities', array(
'methods' => 'POST',
'callback' => 'create_city_from_data'
));
And for testing I am trying to return the request like this
function create_city_from_data($req) {
return ['req' => $req];
}
but always i receive empty object as response, whatever i send in payload i didn't receive anything.
My payload is something like this
{ name: 'Hello', population: 565656 }
This is what is received from the request
{"req":{}}
By using below code you can view your payload.
add_action('rest_api_init', function () {
register_rest_route( 'api/v1', '/cities', array(
'methods' => 'POST',
'callback' => 'create_city_from_data'
));
});
function create_city_from_data($req) {
$response['name'] = $req['name'];
$response['population'] = $req['population'];
$res = new WP_REST_Response($response);
$res->set_status(200);
return ['req' => $res];
}
I have used postman to view the POST parameter
By using this function you can see all post of your custom post type in API...
Get All Post in your API Viewer.
Writer URL on your API viewer (e.g. I used Postman json api view, google chrome adon)
Domain-name/wp-json/showFavorites/v2?post_type=hotel
Here 'hotel' is the custom posttype.
Add this function in your functions.php
add_action( 'rest_api_init', 'wp_api_show_favorites_endpoints' );
function wp_api_show_favorites_endpoints() {
register_rest_route( 'showFavorites', '/v2', array(
'methods' => 'GET',
'callback' => 'showFavorites_callback',
));
}
function showFavorites_callback( $request_data ) {
global $wpdb;
$data = array();
$table = 'wp_posts';
$parameters = $request_data->get_params();
$post_type = $parameters['post_type'];
if($post_type!=''){
$re_query = "SELECT * FROM $table where post_type='$post_type'";
$pre_results = $wpdb->get_results($re_query,ARRAY_A);
return $pre_results;
}else{
$data['status']=' false ';
return $data;
}
}
And using this you can post your content from API
// POST All Posts using API
add_action( 'rest_api_init', 'wp_api_add_posts_endpoints' );
function wp_api_add_posts_endpoints() {
register_rest_route( 'addPost', '/v2', array(
'methods' => 'POST',
'callback' => 'addPosts_callback',
));
}
function addPosts_callback( $request_data ) {
global $wpdb;
$data = array();
$table = 'wp_posts';
// Fetching values from API
$parameters = $request_data->get_params();
$user_id = $parameters['user_id'];
$post_type = $parameters['post_type'];
$post_title = $parameters['post_title'];
$the_content = $parameters['the_content'];
$cats = $parameters['cats'];
$the_excerpt = $parameters['the_excerpt'];
$feature_img = $parameters['featured_image'];
// custom meta values
$contact_no = $parameters['contact_no'];
$email = $parameters['email'];
$hotel_url = $parameters['hotel_url'];
if($post_type!='' && $post_title!=''){
// Create post object
$my_post = array(
'post_title' => wp_strip_all_tags( $post_title),
'post_content' => $the_content,
'post_author' => '',
'post_excerpt' => $the_excerpt,
'post_status' => 'publish',
'post_type' => $post_type,
);
$new_post_id = wp_insert_post( $my_post );
function wp_api_encode_acf($data,$post,$context){
$customMeta = (array) get_fields($post['ID']);
$data['meta'] = array_merge($data['meta'], $customMeta );
return $data;
}
if( function_exists('get_fields') ){
add_filter('json_prepare_post', 'wp_api_encode_acf', 10, 3);
}
// Set post categories
$catss = explode(',', $cats);
if (!empty($catss)) {
if ($post_type == 'post') {
wp_set_object_terms( $new_post_id, $catss, 'category', false );
}
else{
wp_set_object_terms( $new_post_id, $catss, 'Categories', false ); // Executes if posttype is other
}
}
// Set Custom Metabox
if ($post_type != 'post') {
update_post_meta($new_post_id, 'contact-no', $contact_no);
update_post_meta($new_post_id, 'email', $email);
update_post_meta($new_post_id, 'hotel-url', $hotel_url);
}
// Set featured Image
$url = $feature_img;
$path = parse_url($url, PHP_URL_PATH);
$filename = basename($path);
$uploaddir = wp_upload_dir();
$uploadfile = $uploaddir['path'] . '/' . $filename;
$contents= file_get_contents($feature_img);
$savefile = fopen($uploadfile, 'w');
chmod($uploadfile, 0777);
fwrite($savefile, $contents);
fclose($savefile);
$wp_filetype = wp_check_filetype(basename($filename), null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => $filename,
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $uploadfile );
if ($attach_id) {
set_post_thumbnail( $new_post_id, $attach_id );
}
if ($new_post_id) {
$data['status']='Post added Successfully.';
}
else{
$data['status']='post failed..';
}
}else{
$data['status']=' Please provide correct post details.';
}
return ($data);
}
The object parameter passed into the callback function is a WP_REST_REQUST object and has a get_body() method on it which returns the payload/post body of the HTTP Post Request.
function create_city_from_data(WP_REST_Request $req) {
$body = $req->get_body()
return ['req' => $body];
}
I learnt about this today whilst reading this article
You can also declare the type of object in the method signature in case you need to search the documentation for it (like i have above).
CURL request :
$url = $your_url; // your url should like: http://host.com/wp-json/v1/'.$key
$post_string = json_encode($post_data);// make json string of post data
$ch = curl_init(); //curl initialisation
curl_setopt($ch, CURLOPT_URL, $url); // add url
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // get return value
curl_setopt($ch, CURLOPT_POST, true); // false for GET request
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string); // add post data
curl_setopt($crl, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($post_string))
);// add header
$output = curl_exec($ch);
curl_close($ch); // close curl
$error = curl_error($ch); // get error
if(!$error){
return json_decode($output);
}else{
return $error;
}
For Handle Request in PLUGIN context :
public static function handle_requests(WP_REST_Request $request){
$return_data = [];
//get GET params
$key = $request['key'];
//get POST values
$post_data = json_decode($request->get_body());
//$return_data = $post_data;
if ( empty( $return_data ) ) {
return new WP_Error( 'error', 'Invalid Request', array( 'status' => 404 ) );
}else{
return $return_data;
}
}
Your WP REST API ACTION :
add_action( 'rest_api_init', function () {
register_rest_route( '/v1', '/(?P<key>[\w]+)', array(
'methods' => ['GET', 'POST'],
'callback' => 'YOUR_CLASS::handle_requests',
'permission_callback' => '__return_true'
) );
} );
//permission_callback need to add for wordpress newer versions.

Batching with Google Places: Is it possible?

I was wondering if it's possible to send batched requests to maps.googleapis.com. As far as I can tell, it isn't.
I was using the Google API Client Library with supports batching, but it's only for www.googleapis.com. I went ahead and hacked it so that I could call the Places API, and it worked fine for normal calls, but when I actually tried to batch them, I got a 404 error:
"The requested URL /batch was not found on this server. That’s all we know."
So it appears that maps.googleapis.com does not support batching, but I wanted to be sure this is true. If anyone knows otherwise, please tell me how. Thanks!
inside google-api-php-client/src/Google/Config.php:
- 'base_path' => 'https://www.googleapis.com',
+ 'base_path' => 'https://maps.googleapis.com',
google-api-php-client/src/Google/Service/Maps.php:
(I added this file to make Places calls possible.)
<?php
class Google_Service_Maps extends Google_Service
{
const MAPS = "https://maps.googleapis.com/auth/maps";
public function __construct(Google_Client $client)
{
parent::__construct($client);
$this->servicePath = 'maps/api/';
$this->version = 'v3';
$this->serviceName = 'maps';
$this->places = new Google_Service_Maps_Places_Resource(
$this,
$this->serviceName,
'places',
array(
'methods' => array(
'autocomplete' => array(
'path' => 'place/autocomplete/json',
'httpMethod' => 'GET',
'parameters' => array(
'input' => array(
'location' => 'query',
'type' => 'string',
'required' => true,
),
'sensor' => array(
'location' => 'query',
'type' => 'boolean',
'required' => true,
),
'location' => array(
'location' => 'query',
'type' => 'string',
),
'radius' => array(
'location' => 'query',
'type' => 'integer',
),
),
),
)
)
);
}
}
class Google_Service_Maps_Places_Resource extends Google_Service_Resource
{
public function autocomplete($input, $lat, $lng, $radius, $optParams = array())
{
$params = array('input' => $input, 'location' => "$lat,$lng", 'radius' => $radius, 'sensor' => false);
$params = array_merge($params, $optParams);
return $this->call('autocomplete', array($params));
}
}
API batch calling code:
<?php
const API_KEY = 'MY_API_KEY';
set_include_path("google-api-php-client/src/" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Maps.php';
require_once 'Google/Http/Batch.php';
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$client->setDeveloperKey(API_KEY);
$client->setUseBatch(true);
$batch = new Google_Http_Batch($client);
$service = new Google_Service_Maps($client);
$inputs = array(
'Dolore',
'MacAl',
'App Aca'
);
foreach($inputs as $input) {
$req = $service->places->autocomplete($input, 37.7833, -122.4167, 500);
$batch->add($req, $input);
}
$results = $batch->execute();
print_r($results);
print_r($req);

Drupal autocomplete, callback with multiple parameters

I am adding some autocomplete on a form alter. The problem is that in the callback, only the string in the textfield The autocomplete is on, is available. I also want to access a value from another textfield in the callback. How is this possible ?
/**
* Implements hook_form_alter().
*/
function webform_conversion_jquery_form_webform_client_form_1_alter(&$form, &$form_state, $form_id) {
//Load some extra function to process data
module_load_include('inc', 'webform_conversion_jquery', '/includes/dataqueries');
//Add extra js files
drupal_add_js(drupal_get_path('module', 'webform_conversion_jquery') . '/js/conversionform.js');
$form['submitted']['correspondentadress']['cor_street']['#autocomplete_path'] = 'conversionform/conversion_street';
}
}
/**
* Implements hook_menu().
*/
function webform_conversion_jquery_menu() {
$items = array();
$items['conversionform/conversion_street'] = array(
'title' => 'Conversion street autocomplete',
'page callback' => 'conversion_street_autocomplete',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Retrieve a JSON object containing autocomplete suggestions for streets depending on the zipcode.
*/
function conversion_street_autocomplete($street = '') {
$street = "%" . $street . "%";
$matches = array();
$result = db_select('conversion_adresslist')
->fields('conversion_adresslist', array('street'))
->condition('street', $street, 'like')
->execute();
foreach ($result as $street) {
$matches[$street->street] = $street->street;
}
drupal_json_output($matches);
}
I just want to be able to post extra information in the function:
conversion_street_autocomplete($street = '', $extraparameter)
I had the same problem and have figured out a way, which is not too strenuous. It involves overriding the textfield theme and then passing your parameter to the theme function.
First create declare your theme function:
function mymodule_theme() {
$theme_hooks = array(
'my_module_autocomplete' => array(
'render element' => 'element',
),
);
return $theme_hooks;
}
Next we need to add the theme and the variable to our form element. In my case, the form element is part of a field widget:
function my_module_field_widget_form($form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
if($instance['widget']['type'] == 'my_module_field_type') {
$element['my_module_field'] = array(
'#type' => 'textfield',
'#autocomplete_path' => 'my-module/autocomplete',
// THIS IS THE IMPORTANT PART - ADD THE THEME AND THE VARIABLE.
'#theme' => 'my_module_autocomplete',
'#my_module_variable' => $field['field_name'],
);
}
return $element;
}
Then implement the theme function. This is a copy of theme_textfield from includes/form.inc with one important difference - we append the variable to the autocomplete path:
function theme_my_module_autocomplet($variables) {
$element = $variables['element'];
$element['#attributes']['type'] = 'text';
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength'));
_form_set_class($element, array('form-text'));
$extra = '';
if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) {
drupal_add_library('system', 'drupal.autocomplete');
$element['#attributes']['class'][] = 'form-autocomplete';
$attributes = array();
$attributes['type'] = 'hidden';
$attributes['id'] = $element['#attributes']['id'] . '-autocomplete';
// THIS IS THE IMPORTANT PART. APPEND YOUR VARIABLE TO THE AUTOCOMPLETE PATH.
$attributes['value'] = url($element['#autocomplete_path'] . '/' . $element['#my_module_variable'], array('absolute' => TRUE));
$attributes['disabled'] = 'disabled';
$attributes['class'][] = 'autocomplete';
$extra = '<input' . drupal_attributes($attributes) . ' />';
}
$output = '<input' . drupal_attributes($element['#attributes']) . ' />';
return $output . $extra;
}
Now the variable will be available as the first parameter on the autocomplete callback function:
function _my_module_autocomplete($my_module_variable, $search_string) {
// Happy days, we now have access to our parameter.
}
Just in case anyone is still having trouble with this I found a great solution while trying to figure out how to do this. I had a year select list and that dictated what data was displayed in the autocomplete field. The solution basically has an ajax callback function for the select list that can then update the autocomplete field with an extra parameter in the url. Anyways, it is really well explained in the following article.
http://complexdan.com/passing-custom-arguments-drupal-7-autocomplete/
*A note of caution, I was going crazy trying to figure out why it did not work and it turns out you can't have the same form on the page twice (I needed to because I was displaying it differently for mobile devices) because you are using an id for the ajax callback. I added an extra argument to accomplish that. It is called uniqueid in the below example.
function report_cards_comparison_form($form, &$form_state, $uniqueid) {
$curryear = t('2012');
$form['year_select'] = array(
'#title' => t('School Year'),
'#type' => 'select',
'#options' => array(
'2012' => t('2012'),
'2013' => t('2013'),
'2014' => t('2014'),
'2015' => t('2015'),
),
'#default_value' => $curryear,
'#ajax' => array(
'callback' => 'report_cards_comparison_form_callback',
'wrapper' => $uniqueid,
'progress' => array(
'message' => 'Updating Schools...',
'type' => 'throbber'
),
),
);
$form['choice'] = array(
//'#title' => t('Search By: School Name'),
'#type' => 'textfield',
'#attributes' => array(
'class' => array('school-choice'),
'placeholder' => t('Start Typing School Name...'),
),
'#required' => TRUE,
'#autocomplete_path' => 'reportcards/autocomplete/' . $curryear,
'#prefix' => '<div id="' . $uniqueid . '">',
'#suffix' => '</div>',
);
$form['submit'] = array(
'#type' => 'submit',
'#prefix' => '<div class="submit-btn-wrap">',
'#suffix' => '</div>',
'#value' => t('Search'),
'#attributes' => array('id' => 'add-school-submit'),
);
return $form;
}
/**
* Ajax Callback that updates the autocomplete ajax when there is a change in the Year Select List
*/
function report_cards_comparison_form_callback($form, &$form_state) {
unset($form_state['input']['choice'], $form_state['values']['choice']);
$curryear = $form_state['values']['year_select'];
$form_state['input']['choice'] = '';
$form['choice']['#value'] = '';
$form['choice']['#autocomplete_path'] = 'reportcards/autocomplete/' . $curryear;
return form_builder($form['#id'], $form['choice'], $form_state);
}
and I can call the form by doing this...
print render(drupal_get_form('report_cards_comparison_form', 'desktop-schoolmatches'));
You can do it by overriding methods from autocomplete.js in your own js. Here is example:
(function($) {
Drupal.behaviors.someModuleOverrideAC = {
attach: function(context, settings) {
// Next is copied and adjusted method from autocomplete.js
Drupal.jsAC.prototype.populatePopup = function() {
var $input = $(this.input);
var position = $input.position();
// Show popup.
if (this.popup) {
$(this.popup).remove();
}
this.selected = false;
this.popup = $('<div id="autocomplete"></div>')[0];
this.popup.owner = this;
$(this.popup).css({
top: parseInt(position.top + this.input.offsetHeight, 10) + 'px',
left: parseInt(position.left, 10) + 'px',
width: $input.innerWidth() + 'px',
display: 'none'
});
$input.before(this.popup);
// Do search.
this.db.owner = this;
if ($input.attr('name') === 'field_appartment_complex') {
// Overriden search
// Build custom search string for apartments autocomplete
var $wrapper = $('div.apartments-autocomplete');
var $elements = $('input, select', $wrapper);
var searchElements = {string: this.input.value};
$elements.each(function() {
searchElements[$(this).data('address-part')] = $(this).val();
});
var string = encodeURIComponent(JSON.stringify(searchElements));
this.db.search(string);
}
else {
// Default search
this.db.search(this.input.value);
}
};
}
};
}(jQuery));
In your server callback:
function some_module_autocomplete_ajax($string) {
// Decode custom string obtained using overriden autocomplete js.
$components = drupal_json_decode(rawurldecode($string));
// Do you search here using multiple params from $components
}
Ok, for as far as I can see it is not possible. maybe you can roll your own with the ajax functionality in fapi http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7#ajax
For now I solved it by implementing jquery.ui.autocomplete which is included in drupal 7

Resources