How to use InlineKeyboardButton telegram to write inlineKeyboard? - telegram-bot

I'm trying to write inline keyboard for telegram bot. I read document but I couldn't get anything.
InlineKeyboardButton WeightMenu = new InlineKeyboardButton("2 Kilograms", "2");
I wrote this but i don't Know how can send it to user?
Why there isn't any snippet code in telegram document?
Is there any source with code example?

You can use this code to send the inline keyboard to the user:
var inlineKeyboardMarkup = new InlineKeyboardMarkup
{
InlineKeyboard = new []
{
new [] { new InlineKeyboardButton { Text = "Inline Keyboard button", CallbackData = "demo", Url = ""} }
}
};
var newmsg = new SendMessage(update.Message.Chat.Id, "<b>check my new inline keyboard</b>")
{
ReplyMarkup = inlineKeyboardMarkup,
ParseMode = SendMessage.ParseModeEnum.HTML,DisableNotification = false,DisableWebPagePreview = false
};
WriteMessageToConsole(update.Message.Chat.Id, "_check my new inline keyboard_");
bot.MakeRequestAsync(newmsg).Wait();

Related

Interactive button doesn't work properly when using pub/sub

I'm writing a Hangouts Chat bot in C# that uses pub/sub so I can host the bot on our side of a firewall. Everything seems to work well except interactive buttons within cards. If I create a button with a specific action method name, the bot does receive the CARD_CLICKED message with the appropriate action method name. However, it doesn't seem like the card in the Hangouts Chat app knows a response was sent because the bot ends up getting the CARD_CLICKED message three times before the Hangouts Chat app finally says "Unable to contact Bot. Try again later". I've been using the Google.Apis.HangoutsChat.v1 and Google.Cloud.PubSub.V1 packages from NuGet for the bot.
This is speculation, but it seems like the issue might be that interactive buttons don't work properly through pub/sub. Any help would be appreciated.
Here is a snippet of the code I have:
SubscriptionName subscriptionName = new SubscriptionName(PROJECT_ID, SUBSCRIPTION_ID);
SubscriberServiceApiClient client = SubscriberServiceApiClient.Create();
GoogleCredential credential = GoogleCredential.FromFile(CREDENTIALS_PATH_ENV_PROPERTY).CreateScoped(HANGOUTS_CHAT_API_SCOPE);
HangoutsChatService chatService = new HangoutsChatService(new BaseClientService.Initializer
{
ApplicationName = "My Bot",
HttpClientInitializer = credential
});
while (true)
{
PullResponse response = client.Pull(subscriptionName, false, 3, CallSettings.FromCallTiming(CallTiming.FromExpiration(Expiration.FromTimeout(TimeSpan.FromSeconds(90)))));
if ((response.ReceivedMessages == null) || (response.ReceivedMessages.Count == 0))
Console.WriteLine("Pulled no messages.");
else
{
foreach (ReceivedMessage message in response.ReceivedMessages)
{
try
{
byte[] jsonBytes = message.Message.Data.ToByteArray();
JObject json = JObject.Parse(Encoding.UTF8.GetString(jsonBytes));
string messageType = (string)json["type"];
switch (messageType)
{
case "MESSAGE":
{
// Get text
string messageText = (string)json["message"]["text"];
Console.WriteLine($"[{messageType}] {messageText}");
// Send response
string spaceName = (string)json["space"]["name"];
SpacesResource.MessagesResource.CreateRequest request = chatService.Spaces.Messages.Create(new Message
{
Cards = new[]
{
new Card
{
Header = new CardHeader
{
Title = "Message Received!"
},
Sections = new[]
{
new Section
{
Widgets = new[]
{
new WidgetMarkup
{
Buttons = new[]
{
new Button
{
TextButton = new TextButton
{
Text = "Click Me!",
OnClick = new OnClick
{
Action = new FormAction
{
ActionMethodName = "ClickedAction"
}
}
}
}
}
}
}
}
}
}
},
Thread = new Thread
{
Name = (string)json["message"]["thread"]["name"]
}
}, spaceName);
Message responseMsg = request.Execute();
break;
}
case "CARD_CLICKED":
{
string actionMethodName = (string)json["action"]["actionMethodName"];
Console.WriteLine($"[{messageType}] {actionMethodName} at {((DateTime)json["message"]["createTime"]).ToString()}");
// Send response
string spaceName = (string)json["space"]["name"];
SpacesResource.MessagesResource.CreateRequest request = chatService.Spaces.Messages.Create(new Message
{
ActionResponse = new ActionResponse
{
Type = "UPDATE_MESSAGE"
},
Text = $"You clicked on '{actionMethodName}'.",
Thread = new Thread
{
Name = (string)json["message"]["thread"]["name"]
}
}, spaceName);
Message responseMsg = request.Execute();
break;
}
default:
{
Console.WriteLine($"[{messageType}]");
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error parsing message: {ex}");
}
}
// Acknowledge the message so we don't see it again.
string[] ackIds = new string[response.ReceivedMessages.Count];
for (int i = 0; i < response.ReceivedMessages.Count; ++i)
ackIds[i] = response.ReceivedMessages[i].AckId;
client.Acknowledge(subscriptionName, ackIds);
}
}
Using buttons with Hangouts Chat API requires a custom answer including:
{
'thread': {
'name': thread_id
},
'actionResponse': {
'type': 'UPDATE_MESSAGE'
}
}
I'd recommend using Hangouts Chat API with a bot URL.

Triggering clearIconTap callback on dynamically created fields

I am creating a simple app using Sencha Touch where I'm dynamically creating container with textfields, textareafields etc. when the user needs to add new container with components. The problem now is when the clear icon on the textareafield is tapped it clears the text, but I would like to know which textareafield has been cleared. Can anyone help me in this please?
This is how I created container .
var childObj2 = {};
childObj2.xtype = 'container';
var type = 'vbox';
var layout = {}
layout.type = type;
childObj1.layout = layout;
var txtarea= {};
txtarea.xtype = 'textareafield';
txtarea.id = "txt51";
txtarea.flex = 3;
txtarea.maxRows = 7;
txtarea.placeHolder = 'Type here';
txtarea.value = value['notes'];
txtarea.inputCls = 'txtareaStyle'
txtarea.clearicontap = "clearText";
How to add clearicontap listener to this?
When you you create a textfield simply add a listener to it for the clearicontap event and that callback will get executed for each of the fields.
For example:
var container = Ext.create('Ext.Container', {});
for (var i=1; i<=3; i++) {
var field = Ext.create('Ext.field.Text', {
id: 'textfieldnumber' + i,
listeners: {
clearicontap: function() {
alert("Tapped clear icon on text field number: " + i + "!");
}
}
});
container.add(field);
}
[EDIT]
I answer the question you make after your edit:
I am using the standard way of creating Sencha components through Ext.create(), and I would suggest you to switch to the same way. It is not clear by the code you posted how those Javascript objects are actually transformed into Ext components. Anyway, they are very likely components configurations, so I guess you could try:
txtarea.listeners = {
clearicontap: function() {
alert("Tapped clear icon on text field");
}
}

Worklight multiple busyIndicators

Is it possible to have many busyIndicators depending on context?
I tried with 4, but it doesn't work (only the last busyIndicator seems to be used, and can't be hidden):
Here's the code:
var myBusyIndicator1;
var myBusyIndicator2;
var myBusyIndicator3;
var myBusyIndicator4;
wlCommonInit(){
myBusyIndicator1 = new WL.BusyIndicator('content', {text : 'Loading data 1'});
myBusyIndicator2 = new WL.BusyIndicator('content', {text : 'Loading data 2'});
myBusyIndicator3 = new WL.BusyIndicator('content', {text : 'Loading data 3'});
myBusyIndicator4 = new WL.BusyIndicator('content', {text : 'Loading data 4'});
}
$('#myPage').on('showpage', function(e, ui){
myBusyIndicator1.show(); // 'Loading data 4' is displayed in modal window
//do some stuff
myBusyIndicator1.hide(); // modal window still, and app is not responsive anymore
});
"Busy indicator is a singleton. If you create several busy indicators, show them and then hide of them - all will be hidden." - Anton (source)
You could try to wrap it in your own "singleton", for example:
var Busy = (function () {
var busyObject;
var _show = function (message, options) {
//If you're using WL v6.0,
//see: https://stackoverflow.com/q/18501456/186909
WL.ClientMessages.loading = message;
//Others version of WL may not require
//the line above or the message parameter.
busyObject = new WL.BusyIndicator('content', options);
busyObject.show();
};
var _hide = function () {
if (busyObject !== null) {
busyObject.hide();
busyObject = null;
}
//else no busy indicator to hide
};
return {
show: _show,
hide: _hide
};
}());
//Usage:
Busy.show('message1', options1);
//Later...
Busy.hide();
//Later...
Busy.show('message2', options2);
//Later...
Busy.hide();
I did not test the code above, it's just meant to give the reader ideas, not to be copy/pasted into a project.

Can you load the PopupAppender on demand?

I am trying to use log4javascript and was wondering if there is any way to load the PopupAppender on demand.
I am seeking functionality much like the in-browser tools, where there would be an icon in my application that indicates that something has been logged and when I click it, the PopupAppender opens and allows me to view the logs.
I'm thinking I could write my own very simple appender to show the icon if there are errors, but i'm not sure how I could load up the PopupAppender and show historic messages?
You'd have to have some kind of proxy appender, as you suggest, which stores logging messages and creates a PopUpAppender on demand. Something like this:
Demo: http://jsfiddle.net/hDRpT/
Code:
function OnDemandPopUpAppender() {
this.popUpAppender = new log4javascript.PopUpAppender();
this.poppedUp = false;
this.popperUpperDisplayed = false;
this.queuedLoggingEvents = [];
}
var proto = new log4javascript.Appender();
OnDemandPopUpAppender.prototype = proto;
proto.appendQueued = function() {
for (var i = 0, loggingEvent; loggingEvent = this.queuedLoggingEvents[i++]; ) {
this.popUpAppender.append(loggingEvent);
}
this.queuedLoggingEvents.length = 0;
};
proto.popUp = function() {
this.poppedUp = true;
this.appendQueued();
};
proto.append = function(loggingEvent) {
var appender = this;
this.queuedLoggingEvents.push(loggingEvent);
if (this.poppedUp) {
this.appendQueued();
} else if (!this.popperUpperDisplayed &&
loggingEvent.level.isGreaterOrEqual(log4javascript.Level.ERROR)) {
var popperUpper = document.createElement("div");
popperUpper.style.border = "solid red 2px";
popperUpper.innerHTML = "There are error messages in the log. Click to open.";
popperUpper.onclick = function() {
appender.popUp();
}
document.body.appendChild(popperUpper);
this.popperUpperDisplayed = true;
}
};
var log = log4javascript.getLogger("main");
log.addAppender(new OnDemandPopUpAppender());
log.debug("A debug message");
log.error("A horrible error!");

HTML5 Drag n Drop File Upload

I'm running a website, where I'd like to upload files with Drag 'n Drop, using the HTML5 File API and FileReader. I have successfully managed to create a new FileReader, but I don't know how to upload the file. My code (JavaScript) is the following:
holder = document.getElementById('uploader');
holder.ondragover = function () {
$("#uploader").addClass('dragover');
return false;
};
holder.ondragend = function () {
$("#uploader").removeClass('dragover');
return false;
};
holder.ondrop = function (e) {
$("#uploader").removeClass('dragover');
e.preventDefault();
var file = e.dataTransfer.files[0],
reader = new FileReader();
reader.onload = function (event) {
//I shoud upload the file now...
};
reader.readAsDataURL(file);
return false;
};
I also have a form (id : upload-form) and an input file field (id : upload-input).
Do you have any ideas?
P.S. I use jQuery, that's why there is $("#uploader") and others.
Rather than code this from scratch, why not use something like html5uploader, which works via drag n drop (uses FileReader etc.): http://code.google.com/p/html5uploader/
EDIT: apparently we respondents are supposed to tend to our answers forever more, for fear for down-votes. The Google Code link is now dead (four years later), so here's a jQuery plugin that is very similar: http://www.igloolab.com/jquery-html5-uploader/
You'll want to extract the base64 encoded file contents and ajax them over tot the server.
JavaScript
var extractBase64Data;
extractBase64Data = function(dataUrl) {
return dataUrl.substring(dataUrl.indexOf(',') + 1);
};
// Inside the ondrop event
Array.prototype.forEach.call(event.dataTransfer.files, function(file) {
var reader;
if (!file.type.match(options.matchType)) {
return;
}
reader = new FileReader();
reader.onload = function(event) {
var contentsBase64;
if (event.target.readyState === FileReader.DONE) {
contentsBase64 = extractBase64Data(event.target.result);
return $.post(someURL, {
contentsBase64: contentsBase64
});
}
};
reader.readAsDataURL(file);
});
CoffeeScript
extractBase64Data = (dataUrl) ->
dataUrl.substring(dataUrl.indexOf(',') + 1)
# Inside the ondrop event
Array::forEach.call event.dataTransfer.files, (file) ->
return unless file.type.match(options.matchType)
reader = new FileReader()
reader.onload = (event) ->
if event.target.readyState == FileReader.DONE
contentsBase64 = extractBase64Data(event.target.result)
$.post someURL,
contentsBase64: contentsBase64
reader.readAsDataURL(file)