botman / web-widget

MIT License
37 stars 68 forks source link

Is there a way to send attachments from web widget? #23

Open avorozheev opened 5 years ago

avorozheev commented 5 years ago

image

I'm using Botman WebWidget implementation from tutorial here: https://botman.io/2.0/driver-web

But it doesn't seem to have an attachment functionality: neither button, nor drag-n-drop into the chat window. Also surfed in documentation and related issues - no even mention of attachment functionality in web widget.

Am I doing something wrong, or it is really not implemented?

claretnnamocha commented 5 years ago

If you wish to upload files you may need to redesign your interface and implement the upload function your self using javascript.
Basically, the driver supports it but the original interface does not provide for it.
The implementation in javascript looks like this:

var form = new FormData();
form.append("driver", "web");
form.append("attachment", "file");
form.append("file", "");

var settings = {
  "url": "http://localhost:500",
  "method": "POST",
  "timeout": 0,
  "processData": false,
  "mimeType": "multipart/form-data",
  "contentType": false,
  "data": form
};

$.ajax(settings).done(function (response) {
  console.log(response);
});

Explanation:

menno-dev commented 4 years ago

@claretnnamocha where do I have to add this code? Into which file?

claretnnamocha commented 4 years ago

It could be in a file or script that handles the upload event on your interface @menno-dev

menno-dev commented 4 years ago

@claretnnamocha mhm.. unfortunately I have no clue. Where could it be within Botman Studio? Thank you very much!

claretnnamocha commented 4 years ago

It could be in a file or script that handles the upload event on your interface @menno-dev

This upload code is written on the front-end not in the back-end

diosdado93 commented 3 years ago

@claretnnamocha could you help me with an example of implementation? do I have to copy paste your code in my front end and that all? which parameter do I have to change? do you have any working example that will help me please?

@avorozheev have you finaly found a solution? @menno-dev have you found a solution? Thank you very much for your help

nachoampu commented 3 years ago

Hi, any news on this issue? I am currently trying to implement this solution but don´t know where should I put this code or if something is missing. Thanks!

arch2603 commented 3 years ago

Just wondering if there is any more help with this issue as I am having the same dilemma uploading images via the web widget.

teevon commented 2 years ago

There is a way. It's entirely a front-end issue, on the back-end you can listen for images, video, and attachments in general however you want to. but from the front-end here's how things work (at least for me) I use the botman widget by using two js script files on the front-end, A widget.js file on the main page, and a chat.js on a second page. The second page is the page the the frameEndpoint property of the botmanWidget object (The botmanWidget object remember is the object used to configure certain properties of botman from the main page) now in that page that the frameEndpoint property targets, That is where changes to the interface can be implemented here's how the page looks from my point of view

<html>
<head>
    <title>Widget Body</title>
    <!-- <link rel="stylesheet" type="text/css" href="static/css/chat.min.css"> -->
    <link href="static/bootstrap-4.1.3/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="static/css/font-awesome-4.7.0/css/font-awesome.css">
    <link rel="stylesheet" type="text/css" href="static/css/chat.css">
    <link rel="stylesheet" type="text/css" href="static/css/styles_attachment.css">
</head>
<body>
    <script src="static/js/jquery-1.10.2.min.js"></script>
    <script src="static/bootstrap-4.1.3/js/bootstrap.min.js"></script>
    <script id="botmanWidget" src='static/js/chat.js?v=1'></script>
    <script src="static/js/chat_changes.js?v=1"></script>
    <div id="fileApp"></div>
    <div class="div-attachments-container">
        <div class="div-attachments">
            <span id="view-audio" class="view-attachment-left fa fa-file-audio-o"></span>
            <span id="view-video" class="view-attachment-left fa fa-file-video-o"></span>
            <span id="view-file-name" class="view-attachment-left"></span>
            <span id="send" class="view-attachment-right fa fa-paper-plane" en="true"></span>
        </div>
    </div>
    <script src='static/js/bot_attachment.js?v=1'></script>
</body>
</html>

Two script files do the most of my magic for me, the chat_changes.js (This file helps me adjust the appearance of changes I make to the interface) and bot_attachment.js (Here I upload the selected file to the server) files

Here's what my bot_attachment.js file looks like

$(document).ready(function () {
    document.getElementById('fileApp').innerHTML = `
         <div>
          <input style="display:none" type="file" id="fileInput" />
         </div>
        `;

    const fileInput = document.querySelector("#fileInput");
    var file_type;
    var files;

    $("#view-video").on("click", function(e){
        file_type = "video";
        fileInput.click();
    });

    $("#view-audio").on("click", function(e){
        file_type = "audio";
        fileInput.click();
    });

    $("#send").on("click", function(e){
        if(($("#view-file-name").text() == "") || (files == null)) return;
        sendFile(files[0], file_type);
    });

    $("#fileInput").on("change", function(e){
        console.log("File here");
        files = e.target.files;
        console.log(files);
        if (files.length > 0) {
            $("#view-file-name").text(files[0]["name"]);
        }

    });

    function sendFile(file, filetype){
        var form = new FormData();
        form.append("driver", "web");
        form.append("attachment", filetype);
        form.append("interactive", 0);
        form.append("file", file);
        form.append("userId", "replace with 0 or your preferred value");
        var settings = {
            "url": "https://chatbot/server",
            "method": "POST",
            "timeout": 0,
            "processData": false,
            "mimeType": "multipart/form-data",
            "contentType": false,
            "data": form
        };
        $.ajax(settings).done(function (response) {
            files = null;
            $("#fileInput").val(null);
            $("#view-file-name").text("");
            window.parent.postMessage(response, '*');
        });
    }
});

here's what my chat_changes.js file looks like

window.addEventListener('load', function () {
    var messageArea = document.getElementById("messageArea");
    var userText =  document.getElementById("userText");
    var chatOl = document.getElementsByClassName("chat")[0];
    var messageAreaHeight = messageArea.clientHeight;
    chatHeight = chatOl.clientHeight;
    messageArea.style.height = (messageAreaHeight - 20) + "px";
    chatOl.style.height = (chatHeight - 20) + "px";
    userText.setAttribute("autocomplete","off");
    userText.style.position = "absolute";
    userText.style.bottom = "40px";
});

now so far, this allows you send files to the server as long as you have the

$botman->receivesVideos(function($bot, $videos){
 //some code to run here for receiving videos
});

or

$botman->receivesAudio(function($bot, $videos){
 //some code to run here for receiving audios
});

similar functions exists for files and images and whatever now all this makes sure the server works with receiving files, but the servers response doesn't get back to your application the way it is wired up by the botman widget by default anymore, here where you get a bit creative. The botman widget on the main page exposes and object window.botmanChatWidget This widget has an api writeToMessages, which allows us write replies from our server.

if you notice in the bot_attachment I use the postMessage method to post a a message from the iframe back to my main page I use that action to trigger a function, now on the main page in a file I called botmanTest.js the function is handleMessage and here's what the script looks like

here's what the code looks like, in a script file I named botmanTest.js (you can use whatever name of course)

$(document).ready(function() {
    const botmanInterval = setInterval(checkBotman, 1000);
    function checkBotman(){
        if(window.botmanChatWidget != "undefined"){
            clearInterval(botmanInterval);
        }
    }

    if(!window.addEventListener){
        // IE8 support
        window.attachEvent('onmessage', handleMessage);
    } else {
        window.addEventListener('message', handleMessage, false);
    }

    function handleMessage(event){
        if(event.origin == ''){
            //just some code to constrain the origin if I need to
        }
        var json_response = JSON.parse(event.data);
        (json_response.messages || []).forEach(function (t) {
            window.botmanChatWidget.writeToMessages(t);
        });
    }
});

i use a tacky method to make sure I'm not using the botmanChatWidet object before it is defined. Documentation for botman web widget isn't all so well set up. Hopefully this would help someone

teevon commented 2 years ago

Here's the stylesheet code for the styles_attachment.css files

.view-attachment-left { z-index: 999999999999999999; padding-left: 20px; cursor: pointer; } .view-attachment-right { z-index: 999999999999999999; padding-right: 10px; display: inline-block; cursor: pointer; position: absolute; right: 0px; } .div-attachments-container { height: 30px; width: 100%; display: inline-block; position: fixed; bottom: 8px; } .div-attachments { margin-top: 10px; position: relative; }

NowakAdmin commented 1 year ago

it is possible to use above code inside conversations? i try to catch an image inside conversation and it seems that image is sended directly to routes/botman.php in my fallback function.

teevon commented 1 year ago

it is possible to use above code inside conversations? i try to catch an image inside conversation and it seems that image is sended directly to routes/botman.php in my fallback function.

The problem is with the userId in the form, make sure the right id is being passed there, I had issues with that too

teevon commented 1 year ago

form.append("userId", make very sure the right userId is appearing here, else the default response gets activated like there is no on going conversation)

Just make sure the right userId is being passed in there, it should work fine afterwards. I Encountered the same problem too, took me a while to figure it out

vaamoz commented 7 months ago

shdi

vaamoz commented 7 months ago

the code u have refere is not working