benjick / meteor-telegram-bot

Telegram bot plugin for Meteor
24 stars 15 forks source link

Demo Request: sendPhoto #12

Open alexivanovvv opened 8 years ago

alexivanovvv commented 8 years ago

Hey, is there any way to see a demo for sendPhoto? Can't figure it out…

benjick commented 8 years ago

Hey, can you try this? https://github.com/benjick/meteor-telegram-bot/issues/1#issuecomment-131053638

alexivanovvv commented 8 years ago

Thanks for the tip. I had to change the code from that example a bit, since Meteor was asking for callback to have its own fiber. However, still no luck: Telegram returns [Error: failed [400] {"ok":false,"error_code":400,"description":"[Error]: Bad Request: Wrong persistent file_id specified: contains wrong characters or have wrong length"}] stack: [Getter] on this code:

     fs = Npm.require('fs');
      TelegramBot.addListener('/senddoc', function(command, username, original) {
        fs.readFile('/etc/hosts', 'utf8', Meteor.bindEnvironment(function (err,data) {
          if (err) {
            console.log(err);
            return;
          }
          TelegramBot.method('sendDocument', {
            chat_id: original.chat.id,
            document: data,
          })
        }));

      });
alexivanovvv commented 8 years ago

another challenge is to get a picture file from a specific url to be uploaded with sendPhoto. I tried to do it with CollectionFS, but didn't succeed. fs.readStream didn't help either, so I'm a bit lost now.

alexivanovvv commented 8 years ago

Ended up using external php file to pass images. Not the best option, but does the job.

benjick commented 8 years ago

Can you describe the whole flow for me? What you are doing from a to b On Feb 17, 2016 23:24, "epleplepl" notifications@github.com wrote:

Ended up using external php file to pass images. Not the best option, but does the job.

— Reply to this email directly or view it on GitHub https://github.com/benjick/meteor-telegram-bot/issues/12#issuecomment-185434811 .

alexivanovvv commented 8 years ago

Hey, thanks for reply. I'm writing a bot that helps one memorize names.

On /start the sequence happens:

  1. The bot sends a picture and a question "Who is this person?", randomly selected from a larger set of people.
  2. Custom keyboard is shown with four names (one of them of the person)
  3. The user replies with one of the names
  4. The bot replies with either confirmation or a message with the correct name.
  5. Repeat from 1.

Picture URLs and names are gathered from LinkedIn.

Here is the code I have now:

 TelegramBot.addListener('/start', function(command, username, original) {

    var chatId = original.chat.id;
    //a quiz person is selected from array
    var randomPerson = people.randomElement();

    // Create Keyboard
    kb = {
        keyboard: [
            [randomPerson.name,maleNames.randomElement()],
            [maleNames.randomElement(),maleNames.randomElement()]
        ],
        one_time_keyboard: true,
        resize_keyboard: true
    };

    keyboard = EJSON.stringify(kb);
    var message = "What's the name of this person?";

    //phpImageSendUrl is a variable containing URL to PHP file that posts the picture to the chat by ID
    HTTP.call("GET", phpImageSendUrl, { params: {chatid: chatId, url: randomPerson.imageURL} }, function(error, result) {
        if (!error) {
            TelegramBot.method('sendMessage', {
                chat_id: chatId,
                text: message,
                reply_markup: keyboard
                //reply_to_message_id: original.message.message_id
            });
        }
    });
});

the content of php file:

// PHP
if (isset($_GET['chatid'])) {
    $chatId = $_GET['chatid'];
} else {
    // Fallback behaviour goes here
}

if (isset($_GET['url'])) {
    $imageUrl = $_GET['url'];
} else {
    // Fallback behaviour goes here
}

print_r('botURL:' . $botUrl . '<br/>');
print_r('chat id: ' . $chatId . '<br/>');
print_r('image URL: ' . $imageUrl . '<br/>');

sendPhoto($chatId,$imageUrl);
function sendPhoto($chatId,$photoUrl){
    global $botUrl;
    $url = $botUrl . "sendPhoto?chat_id=" . $chatId;
    $ext = pathinfo($photoUrl, PATHINFO_EXTENSION);
    $localFile = '/tmp/image'  . rand ( 10 , 99) . '.' . $ext;

    copy($photoUrl, $localFile);

    $postFields = array(
        'chat_id' => $chatId,
        'photo' => new CURLFile(realpath($localFile))
    );

    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type:multipart/form-data"
    ));
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields); 
    $output = curl_exec($ch);

    //print_r('Image Sent '. $botUrl . ' '. $photoUrl . ' > ' . $localFile);
}
alexivanovvv commented 8 years ago

Things I didn't figure out yet:

  1. how to send images from Meteor
  2. how to follow up on discussion, that is, learn what user replies and depending on where you are in conversation, reply with corresponding response (e.g. if the name entered was correct, reply 'Good job!')
  3. how to properly loop the whole thing (step 5)

I'd appreciate your feedback and hints, Max.

benjick commented 8 years ago

For (1) can you try this?

var r = request.post('http://service.com/upload', Meteor.bindEnvironment(function(err, httpResponse, body) {
  if (err) {
    return console.error('upload failed:', err);
  }
  console.log('Upload successful!  Server responded with:', body);
}));
var form = r.form()
form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png')))

I will check the rest when I have time

alexivanovvv commented 8 years ago

Thanks for pointing out! Below is the code that finally worked.

  1. May I suggest adding sendPhoto by URL function to the package?
  2. Is there way to use Meteor.npmRequire() without filling in packages.json?
function sendPhoto(chatId,photoURL,callback) {
    if (typeof chatId == 'undefined') {
        console.log('chatId undefined');
        return false;
    }

    if (typeof photoURL == 'undefined') {
        console.log('photoURL undefined');
        return false;
    }

    var sendURL = 'https://api.telegram.org/bot' + TELEGRAM_TOKEN + '/sendPhoto?chat_id=' + chatId;
    var randomPerson = people.randomElement();
    var request = Meteor.npmRequire('request');
    var r = request.post(sendURL, Meteor.bindEnvironment( function(err, httpResponse, body) {
        if (err) {
            return console.error('upload failed:', err);
        }
        console.log('Upload successful!  Server responded with:', body);
    }));

    var form = r.form();
    form.append('photo', request(photoURL));

    if (typeof callback != 'undefined') {
        return callback;
    }
benjick commented 8 years ago

Hey. If you want to do a pull request I'd be happy to merge it.

alexivanovvv commented 8 years ago

Pull request… It’s going to be that day when I finally feel like a proper developer ^_^

ghost commented 8 years ago

guys can u add sendPhoto function to this package?

benjick commented 8 years ago

You can call any method @Evrei, what's the problem?