python – telegram bot InlineKeyboard callback link

I made a telegram bot with python which requests some data from user(like directory), then user_data will send to admin to confirm or reject user_data to publish in a telegram channel.
I have a problem in this part,when admin confirmed, user_data won’t send to channel and empty message sends to channel.
I think I might use callback_query but I don’t know how!

I have problem with inlinebuttonkeyboard callback:
here is the code which user_data sent to admin:

    buttons = (
    (
        InlineKeyboardButton(text='تایید',url= 'https://t.me/kasraproject_bot?start=CONFIRMATION'),
        InlineKeyboardButton(text='رد',url='https://t.me/kasraproject_bot?start=REJECT'),
    ),
    )
    admin_keyboard = InlineKeyboardMarkup(buttons)
    bot.send_photo(
        chat_id='145032913',photo=open('madrak.jpg','rb'),
        caption='جزئیات در زیر ذکر شده استn{}'
        .format(facts_to_str(user_data))+
        'n برای اطلاعات بیشتر با ارسال کننده در ارتباط باشید {}'
        .format(user.name),reply_markup=admin_keyboard
    )

next step after admin confirmed:

if text =='/start CONFIRMATION':
    del user_data('شماره موبایل')
    del user_data('مدرک تحصیلی')

    buttons = (
    (
        InlineKeyboardButton(text='ارسال پیشنهاد', url='https://t.me/kasraproject_bot?start=offer'),
        InlineKeyboardButton(text='مشاهده پیشنهادات ارسالی', url='https://t.me/kasraproject_bot?start=sent_offers'),
        InlineKeyboardButton(text='تعداد متقاضی',url='https://t.me/kasraproject_bot?start=offer'),
    )
    )
    offer_keyboard = InlineKeyboardMarkup(buttons)
    
    bot.send_message(
        chat_id=chat_id,
        text='جزئیات در زیر ذکر شده استn{}'
        .format(facts_to_str(user_data))+
        'n برای اطلاعات بیشتر با ارسال کننده در ارتباط باشید {}'
        .format(user.name),reply_markup=offer_keyboard
        
    )

offer_keyboard is for channel members to offer the user which sent his own data to send requests for contacting to him.

8 – systemAdminMenuBlockPage callback now respecting menu link permissions

I added a custom permission on “admin/commerce/config” to disable access for certain user roles.

class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events(RoutingEvents::ALTER) = 'onAlterRoutes';
    return $events;
  }

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
      if ($route = $collection->get('commerce.configuration')) {
        $route->setRequirements(('_permission' => 'administer commerce configuration'));
      }
  }
}

The page can now only be accessed when user has the permissions ‘administer commerce configuration’. But it is still visible on the “admin/commerce” page.
The page url’s are build by the systemAdminMenuBlockPage callback. The function getAdminBlock (core/modules/system/src/SystemManager.php) builds the menu and has a $element->access->isAllowed function,but this keep returning 1. And so its still printed on the overview page.

Any suggestions for fixing this issue?

Ajax callback to create paragraphs on form

I’m trying to create a way that an end user can upload a csv into a node form and it automatically extracts the content and then creates paragraphs in the form.

Form example

I have created a custom managed file class that I’m modifying the uploadAjaxCallback function and it extracts the csv contents and I can set some html under the file field using and ajaxCommand but I want to replace or append paragraphs to the existing field.

  public static function uploadAjaxCallback(&$form, FormStateInterface &$form_state, Request $request) {
    // load the CSV document from a file path
    $absolute_path = Drupal::service('file_system')->realpath('private://catalogue_import/orders.csv');
    $encoder = new CsvEncoder();
    $data = $encoder->decode(file_get_contents($absolute_path), 'csv');

    // Return the paragraph element.
    $content = '<table><thead><th>UID</th><th>Email</th></thead><tbody>';
    foreach ($data as $row){
      $content .= '<tr><td>' . $row('Uid') . '</td><td>'. $row('Email') .'</td></tr>';
    }
    $content .= '</tbody></table>';
    $Selector = '.harps-file'; /* See: https://www.w3schools.com/cssref/css_selectors.asp */
    $response = parent::uploadAjaxCallback($form, $form_state, $request);
    $response->addCommand(new HtmlCommand($Selector,$content));

    return $response;

  }

If I return the paragraph field in the response then it replaces the file upload.

Is what I’m trying to do even achievable ?

Thanks

plugins – Callback hooked to post_updated firing on new posts as well

Context: I’m using a plugin that allows me to add author boxes throughout my site (Simple Author Box), while providing an easy way for any user to update their social media links and profile pictures. I figured I could also leverage that plugin to dynamically show the team members in the site’s about section.

However, I didn’t want to have author archives for the team members that won’t be publishing any posts in the future (designer, myself etc.), so I used the solution from this question as a starting point to disable specific users’ author archives and from there I created a few additional functions in order to automate that functionality (author archives are now automatically being disabled/enabled according to the number of posts each user has published).

One of these functions is hooked to post_updated, which according to the docs: “Fires once an existing post has been updated.” (emphasis added)

Here’s the function’s code (please forgive any lack of good practices, I’m new to PHP and not an experienced programmer):

/* 
* This function does the checks and the actual value update, if needed.
* It's called from inside the callback.
*/
function maybe_update_author_archive_status($user_id, $published_posts, $author_archive_disabled) {
    if ($published_posts == 0 && $author_archive_disabled != 'on') {
        update_user_meta($user_id, '_author_archive_disabled', 'on');
    } elseif ($published_posts != 0 && $author_archive_disabled != 'off') {
        update_user_meta($user_id, '_author_archive_disabled', 'off');
    }
}

/* 
* The callback itself.
*/
function maybe_update_author_archive_status_on_post_update($post_id, $post_after, $post_before) {
    if($post_before->post_status != 'publish' && $post_after->post_status != 'publish') {
        return;
    }
    
    $old_author = $post_before->post_author;
    $new_author = $post_after->post_author;
    $authors = array($old_author);
    
    /* If the post author has changed, I might need to update both author archive status */
    if($new_author != $old_author) {
        $authors() = $new_author;
    }

    foreach($authors as $author) {
        $user_id = intval($author, 10);
        $author_archive_disabled = get_user_meta($user_id, '_author_archive_disabled', true);
        $published_posts = count_user_posts($user_id);

        maybe_update_author_archive_status($user_id, $published_posts, $author_archive_disabled);
    }
}
add_action('post_updated', 'maybe_update_author_archive_status_on_post_update', 10, 3);

However, to my surprise (and delight actually), it’s also firing when I create and publish a new post. Can anyone explain me why? Under which circumstances this function wouldn’t be fired? Even though this is the behavior I desired and everything is working as I wanted it to, this is not what I expected it would happen after reading the documentation.

8 – Ajax Callback to Update Select List not Working

I have defined couple of fields inside my custom entity basefielddefinitions() like so…
$fields('product_line') = BaseFieldDefinition::create('entity_reference')...

$fields('product') = BaseFieldDefinition::create('entity_reference')....

Then in entity form class (ProductLineForm.php), I try to attach an ajax callback to my product_line select list such that it populates the product select list, like this

    $form('product_line')('#group') = 'details';
    $form('product_line')('#ajax') = (
      'callback' => '::populateProducts',
      'event' => 'change',
      'wrapper' => 'edit-products'
    );

Then my product select list looks like this…

    $form('product')('#group') = 'details';
    $form('product')('#attributes') = (
      'id' => 'edit-products',
    );

and then my populateProducts() function…

  public function populateProducts(array $form, FormStateInterface $form_state) {
    $form('product')('#options') = ('1' => 'One', '2' => 'Two');
    $form_state->setRebuild(TRUE);
    $response = new AjaxResponse();
    $option = "<option value='45'>Just testing</option>";
    $response->addCommand(
      new DrupalCoreAjaxReplaceCommand(
        '#edit-products',
        ($form('product'))
      )
    );
    
    return $response;
  } 

The problem is that nothing whatsoever happens, no signs of any ajax call, and the product select list stays empty as it always been.

(1)Is the the entityform class the right place for me to attach an #ajax call to a field defined in a custom entity? Or do I need a hook? Meanwhile I’ve done a lot of other modifications on the custom fields here in this entity form edit class (like grouping into fieldsets, vertical tabs and even modifying weight (eg $form('product_line')('#weight') = 3 – and they all work, why not $form('product_line')('#ajax')….?

(2) Is there a way of attaching the ajax callback directly inside my custom entity’s basefielddefinitions where I define the fields, I would prefer that…

Really stuck on this one, folks, please could someone help me? Appreciate all your input, Thank you all.

8 – How to add an Ajax call to an element that already has callback set?

I want to add an ajax callback to a form element inside a form_alter, but it already has 2 callbacks assigned to it.

When I review:

$form['payment_information']['payment_method']['#ajax']['callback']

it has 2 callbacks already assigned to it.

If I do this:

$form['payment_information']['payment_method']['#ajax'] = [
  'callback' => '_sia_general_get_fee',
  'event' => 'click',
];

My callback is hit on click; but of course, the other 2 callbacks are wiped out and do not work.

If I add something like this:

$form['payment_information']['payment_method']['#ajax']['callback'][] = '_sia_general_get_fee';

then the other callbacks are called; but mine is not – I suspect since I no longer of an event defined.

I am also not sure how the other ajax calls work when they have no events defined for them.

Is there any way to do this?

Python, Tkinter: Can an array be modified within a button callback without using global variables or defining new classes?

Ideally, I would like to use a built-in approach like tk.StringVar to modify an array (of strings) in a button command, but also need to the modified array to live on so it can be modified in other function calls. The line print(a) in the code below prints an array-like object ('abc', 'gh', 'rstu'), but the line print(a(1)) fails to return gh and the line a.append('xyz') returns an error, suggesting that I can’t directly hijack tk.StringVar to carry the array. What is then my best option, if I should avoid the perils of making the array global and the overhead of defining a class?

import tkinter as tk

def append():
    a = a_var.get()
    print(a)
    print(a(1))
    a.append('xyz')
    a_var.set(a)

window = tk.Tk()
a = ('abc','gh','rstu')
a_var = tk.StringVar(value=a)

tk.Button(window, text='Append', command=append).pack()

window.mainloop()

java – Convert a callback based flow to async iterable

Let’s say I have some event-based flow, for example a “read only” websocket. Normally you set the “onmessage” callback to deal with incoming messages.
Is there some way to access the messages in an async iterator? My goal is to have

async () => {
    for await (const message of SOMETHING(new WebSocket('...'))) {
        // message is the content of the callback
    }
};

I have toyed with promises and queues, but I couldn’t find a way to convert a callback (called multiple times) to an (async-) iterator

c++ – Multithreaded callback – Game Development Stack Exchange

I’m making a multiplayer game where players fight in vehicles, and I am doubting my server architecture. As it will be physics, network and AI intensive I would like to split these 3 topics into their own thread. Perhaps even one thread per AI.

The physics thread will run at a fixed time-step and do the same loop over and over.

  1. Integrate gamestate at fixed timestep of 0,005s (200Hz)
  2. Solve gamestate for constraints and collisions
    One such constraint is a vehicle controller, which is a struct consisting of throttle, steer, brake etc. is applied to a single vehicle.
  3. Callback
    1. The network is called every 6 physics frames, thus the networking runs at ~33Hz
    2. The AI is also called every 6 frames.
      Note: network and AI can be called in lockstep

The AI threads will calculate the next move on a need-by-need basis.

  1. Copy gamestate into private memory
  2. Calculate next move
  3. Update their vehicle controller in the game state

The network thread will

  1. Listen for incoming UDP packets, handle them, apply changes to gamestate such as player’s vehicle controller, bullet spawn
  2. When called for, broadcast the new gamestate to clients
    1. Copy gamestate into private buffer
    2. Create array of differences from last state
      1. Vehicle parts removed/added
      2. Vehicle parts moved/rotated
      3. Players joined/left
      4. Projectile impacts and damages
    3. Pack the differences together and broadcast.
  3. When a new player joins:
    1. grab the last private game state buffer and send it whole
    2. Change gamestate by spawning a vehicle and allocating a controller
  1. Creating threads on the fly has overhead, so I would like to avoid it by pre-creating and “parking” the threads, and calling them when needed. Once called, they do their duty, such as calculate the next move for the AI to make. Then the threads “hibernate”. Note that I don’t want the threads to wait in a busy loop and read some shared memory for “activation”.
  2. The AI and Network threads need to make private copies of the game state, because the physics run so fast the game state might be changed mid-read.
    1. Mitigation 1: swapping game state buffers. Still no guarantee.
    2. Mitigation 2: locking the gamestate. This is a bad idea because the physics should not be held up.

How can I achieve this in C++? Does x86 offer actual interrupts for this? How about other architectures, or are there libraries that do this for me?

Or should I do it another way?

multithreading – C++ callback multithreaded, can unregister itself

With this post, i would like to 1) ask for feedback on below code as it stands:

  • do i apply all best practices for c++20?
  • is it safe?
  • is my way to update a callback from inside a running callback sensible/best?

Based on code and design advice found on stackoverflow (e.g. here), I have written a class that handles listeners registering callbacks to receive messages in multithreaded code (listeners can be added from different threads than the thread that messages are sent from, only one thread every sends messages). This code also needed multiple ways for listeners to unregister themselves:

  1. when the class owning the receiver destructs or is otherwise done receiving: hence add_listener() returns a cookie in the form of a std::list::const_iterator (list because iterators to none of the other elements are invalidated when an element is removed, and other cookies thus stay valid)
  2. when the callback during execution determines it no longer needs further messages, this is handled by returning true (“remove myself please”).

I now run into the situation where a listener callback, when invoked, needs to replace itself with another callback. I can’t call add_listener() as that would deadlock when called from inside an invoked callback. Unless i move to use a std::recursive_mutex instead. That seems heavy.

So instead i have added a replacement list to the broadcaster storing a pair of <listenerCookie, listener> which lists what updates should be done once the current message has been broadcasted to all listeners. The updates are performed at the end of the notify_all function. This guarantees that the old callback is never called again and that the cookie held stays valid but now points to the new callback. But this design seems complicated and unsafe: it required adding an extra member function to the broadcaster class, which should only be called from inside a callback. And that is easy to misuse unless code comments (and the horrible function name :p) saying to only invoke from inside a callback are honored. Or is there a way to ensure a function can only be called by the invoked callback?

Am i missing some simpler solution?

A simpler, but sadly impossible solution i considered was for the callback to return the new callback to register, which would replace the currently registered one (the cookie thus stays valid). But I do not know what my listener’s function signature would then be, as you cannot do something CRTP-like with using statements (using listener = std::function<listener(Message...)>; is invalid) (NB: in reality if this option were possible i’d return a variant with bool as well i guess, as i need to also maintain self-deregistration functionality.)

#include <list>
#include <mutex>
#include <functional>
#include <vector>
#include <utility>

template <class... Message>
class Broadcaster
{
public:
    using listener       = std::function<bool(Message...)>;
    using listenerCookie = typename std::list<listener>::const_iterator;

    listenerCookie add_listener(listener&& r_)
    {
        auto l = lock();
        return targets.emplace(targets.cend(), std::move(r_));
    }
    void remove_listener(listenerCookie it_)
    {
        auto l = lock();
        remove_listener_impl(it_);
    }

    void notify_all(Message... msg_)
    {
        auto l = lock();

        for (auto it = targets.cbegin(), e = targets.cend(); it != e; )
            if ((*it)(msg_...))
                it = remove_listener_impl(it);
            else
                ++it;

        if (!update_list.empty())
        {
            for (auto&& (c_it, r) : update_list)
            {
                // turn cookie into non-const iterator
                auto it = targets.erase(c_it, c_it);    // NB, (c_it, c_it) is an empty range, so nothing is removed
                // update callback
                *it = std::move(r);
            }
            update_list.clear();
        }
    }

    // NB: should only be called from running callback!
    void update_callback_from_inside_callback(listenerCookie it_, listener&& r_)
    {
        update_list.emplace_back(it_, std::move(r_));
    }

private:
    auto lock()
    {
        return std::unique_lock<std::mutex>(m);
    }
    listenerCookie remove_listener_impl(listenerCookie it_)
    {
        return targets.erase(it_);
    }

private:
    std::mutex m;
    std::list<listener> targets;

    std::vector<std::pair<listenerCookie, listener>> update_list;
};