Telegram Bots: Encoding Plus Character / Plus Sign - character-encoding

I am working on a telegram bot which sends telephone numbers to my telegram account. The problem is, that a '+' is converted to a ' ' blank. So every telephone number is wrong.
E.g. '+4915733000000' turns into '4915733000000'. I've tried to use the HTML code &#43 the unicode version \u002B and the url encoding caracter %2B and none of them work.
https://api.telegram.org/botTOKEN/sendMessage?chat_id=MYID&text=Test:\u2031 Unicode:\u002B HTML:+ URL:%2B
Result: Test:‱ Unicode: HTML:
Do you know any possiblility to send a plus sign?
Thanks!

In case someone is using VBA to send Telegram messages with + in them you can replace your string like that:
Dim URL as String
Dim reURL as String
URL = "https://www.webpage.com/product+name/specifics+number" 'etc....
reURL = replace(URL, "+, "%2B")
'send message to telegram code here
For more Encoding info you can visit: https://www.w3schools.com/tags/ref_urlencode.ASP

It is possible to send the plus sign using POST method.
Here's the sample Google App Script code (can be easily adapted to JavaScript).
var options = {
method : "post",
payload: {
method: "sendMessage",
chat_id: "<chat_id_here>",
text: "+something",
parse_mode: "HTML"
}
};
var response = UrlFetchApp.fetch("https://api.telegram.org/bot<YOUR_TOKEN>/", options);
Plus sign can also be easily sent with parse_mode="Markdown".
Just checked (this time on Python using telebot library) that both options work:
bot.send_message(CHAT_ID, "Phone number: +1234567890", parse_mode='Markdown')
bot.send_message(CHAT_ID, "Phone number: +1234567890", parse_mode='HTML')

I had the same problem. I was using Java and Spring's WebClient. The only way to make it work is building WebClient using DefaultUriBuilderFactory and set encoding mode to NONE.
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(url);
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
WebClient webClient = WebClient.builder().uriBuilderFactory(factory).filter(logRequest()).build();
Default is EncodingMode.TEMPLATE_AND_VALUES so if you replace + with %2B the resulting URL is %252B. Setting the encoding mode to NONE doesn't replace any especial characters so I had to replace them manually.
private String replaceUrlSpecialCharacters(String message) {
return message.replace("%", "%25").replace("+", "%2B").replace(" ", "%20").replace("|", "%7C").replace(System.lineSeparator(), "%0A");
}
And now the + sign is shown in my messages.

I'am using PHP and this case was solved with rawurlencode. Below is the code:
public function send_message($tg_msg)
{
$tg_token = ''; // Bot Token
$chat_id = ''; // Chat ID
$url = 'https://api.telegram.org/bot' . $tg_token . '/sendMessage?parse_mode=markdown&chat_id=' . $chat_id;
$curlopt_url = $url . '&text=' . rawurlencode($tg_msg);
$ch = curl_init();
$optArray = array(
CURLOPT_URL => $curlopt_url,
CURLOPT_RETURNTRANSFER => true
);
curl_setopt_array($ch, $optArray);
curl_exec($ch);
curl_close($ch);
}
$msg = 'The message';
send_message($msg);
And now the + sign is shown in my messages.

I got that solved by just using this php function:
utf8_encode(text_to_send)

Related

How do I send an SMS via the Twilio API (using HTTP POST in server-side javascript ) that includes accent characters (for instance ö)?

I'm trying to send an SMS via Twilio's API using an HTTP POST request that is called via server-side javascript in salesforce marketing cloud.
I can successfully send an SMS, the only problem is that accent characters (for instance ö, ü, à, è) are being omitted. So for instance if I send an SMS that should say "Dein persönlicher Rabatt", when I received the SMS, it says "Dein persnlicher Rabatt".
Here is my server-side javascript code:
`<script type="text/javascript" runat="server">
Platform.Load("core", "1");
var accountSid = [accountSid];
var authToken = [authToken];
var auth = Base64Encode(accountSid + ":" + authToken);
var phoneDE = DataExtension.Init("[Data Extension external key]");
var numbers = phoneDE.Rows.Retrieve();
var end = numbers.length;
for (var i=0; i<end; i++) {
var config = {
endpoint: "https://api.twilio.com/2010-04-01/Accounts/[accountSid]/Messages.json",
contentType: "application/x-www-form-urlencoded",
payload : "From=[phone]&To=" + numbers[i]["Phone"] + "&Body=Your cöntract is expiring today, you can sign it here: " + numbers[i]["URL"]
};
Write("Payload" + i + ": " + config.payload + " ");
try {
var httpResult = HTTP.Post(
config.endpoint,
config.contentType,
config.payload,
["Authorization"],
["Basic " + auth]
);
var result = Platform.Function.ParseJSON(httpResult.response);
Write(httpResult.StatusCode);
Write("result" + result);
} catch(error) {
Write("Error: " + Stringify(error));
}
}
</script>`
What do I need to do to ensure that my SMS includes the accent characters and that they are not omitted?
Thank you very much for your help.
Thanks for your answer Swimburger. I didn't get a chance to try it as I found another solution. However I do appreciate your feedback, your solution was the next approach I was going to try.
My solution was to modify the contentType of the POST request to include UTF-8 as the character set:
contentType: "application/x-www-form-urlencoded;charset=UTF-8"
Unfortunately, I don't have access to a Salesforce environment to try out your code, but here's a modified version of your code using node.js.
var accountSid = process.env.TWILIO_ACCOUNT_SID;
var authToken = process.env.TWILIO_AUTH_TOKEN;
var auth = Buffer.from(`${accountSid}:${authToken}`).toString('base64');
var body = new URLSearchParams();
body.append("From", "+12345678901");
body.append("To", "+12345678901");
body.append("Body", "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿĀāĂ㥹");
const request = new Request(
`https://api.twilio.com/2010-04-01/Accounts/${accountSid}/Messages.json`,
{
method: 'POST',
body: body.toString(),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${auth}`
}
}
);
fetch(request)
.then(response => response.json())
.then(jsonBody => console.log(jsonBody))
.catch((error) => {
console.error(error);
});
You need to configure the Twilio Account SID and Auth Token as env variables.
After that, running this script sends an SMS and the SMS contains all the characters.
I'm not sure if you are able to use these node.js APIs, but if you don't, this proves that the issue is caused by Salesforce's Server Side JavaScript APIs.
HTTP.Post probably removes the ö character.
If you do have access to node.js/npm packages, you could also use the Twilio helper library for Node.js.

PHP IMAP parsing body text

I working with php imap and I'm having trouble. I need to fetch the body text and the body html but it doesn't look like it have to be , my code is:
$this->email['bodyHTML'] = quoted_printable_decode(imap_fetchbody($imap, $i, 2.2,FT_PEEK ));
if(trim($this->email['bodyHTML']) == ''){
$this->email['bodyHTML'] = imap_fetchbody($imap, $i, 1.2,FT_PEEK );
}
$this->email['bodyText'] = quoted_printable_decode(imap_fetchbody($imap,$i,1.1,FT_PEEK ));
if(trim($this->email['bodyText']) == ''){
$this->email['bodyText'] = quoted_printable_decode(imap_fetchbody($imap,$i,1,FT_PEEK ));
}
The output when doing var_dump is the text below. but it isn't what email text is:
[bodyHTML] =>
[bodyText] => UGVyIGNvbXBldGVuemEuIEdyYXppZQ0KDQogDQoNCkRhOiBFbWFudWVsZSBQZXJzaWNvIFttYWls dG86ZS5wZXJzaWNvQGJsdXNlcnZpY2UuaXRdIA0KSW52aWF0bzogZ2lvdmVkw6wgMTAgbHVnbGlv IDIwMTQgMTc6NDQNCkE6IENyaW5pdGkgU29uaWENCkNjOiBOYXN0YSBFbWlsaWENCk9nZ2V0dG86 IEZ3ZDogSTogUml2aXN0YSBkaSBkaXJpdHRvIHByb2Nlc3N1YWxlIC0gY29kaWNlIGNsaWVudGUg MDAwMTY1NDc3Mw0KDQogDQoNCkNpYW8gU29uaWEsDQoNCmNvbiBsYSBwcmVzZW50ZSByZXN0aXR1 aWFtbyBsYSBwcmF0aWNhIGluZXJlbnRlIGlsIGNsaWVudGUgYy8xNjU0NzczIGRpIGNvbXBldGVu emEgSXBzb2EuDQoNCkdyYXppZSBFbWFudWVsZQ0KDQoNCg0KLS0tLS0tLS0gTWVzc2FnZ2lvIG9y aWdpbmFsZSAtLS0tLS0tLSANCg0KT2dnZXR0bzogDQoNCkk6IFJpdmlzdGEgZGkgZGlyaXR0byBw cm9jZXNzdWFsZSAtIGNvZGljZSBjbGllbnRlIDAwMDE2NTQ3NzMNCg0KRGF0YTogDQoNCk1vbiwg MTYgSnVuIDIwMTQgMTE6NTQ6MDEgKzAyMDANCg0KTWl0dGVudGU6IA0KDQpDcmluaXRpIFNvbmlh IDxTb25pYS5DcmluaXRpQHdraS5pdD4gPG1haWx0bzpTb25pYS5DcmluaXRpQHdraS5pdD4gDQoN CkE6IA0KDQo8Y2xpZW50aWdpdXJpZGljYUB3a2ltYWlsLml0PiA8bWFpbHRvOmNsaWVudGlnaXVy aWRpY2FAd2tpbWFpbC5pdD4gDQoNCg0KDQoNCg0KDQogIA0KDQogIA0KDQpEYTogTGlhIENhcm9s aW5hIEJhdGlzdGEgQ2ludHJhIFttYWlsdG86bGlhLmJhdGlzdGFAZ21haWwuY29tXSANCkludmlh dG86IG1lcmNvbGVkw6wgMTEgZ2l1Z25vIDIwMTQgMTQ6MjANCkE6IFNob3BXS0k7IEluZm8gQ29t bWVyY2lhbGkgV29sdGVyc0tsdXdlciBJdGFsaWE7IFNlcnZpemlvIENsaWVudGkgVXRldCBHaXVy aWRpY2ENCk9nZ2V0dG86IFJlOiBSaXZpc3RhIGRpIGRpcml0dG8gcHJvY2Vzc3VhbGUgLSBjb2Rp Y2UgY2xpZW50ZSAwMDAxNjU0NzczIA0KDQogIA0KDQpOb24gcmllc2NvIGEgY2FwaXJlIHBlc
That data is base64-encoded. You need to check the Content-Transfer-Encoding header: if it's quoted-printable, decode the data as quoted-printable, as you do in the code above, but if it says base64, decode the data as base64 instead.

OAuth error when exporting Sheet as XLS in Google Apps Script

I had a Google Apps Script to take appointments from my Google Calendar, copy them into a Google Sheet, convert it to XLS and email it. It was working fine until this week.
The initial problem was a 302 error, probably caused by the new version of Sheets. This has been discussed here: Export (or print) with a google script new version of google spreadsheets to pdf file, using pdf options
I got the new location of the file by muting the HTTP exceptions and adjusting the URL accordingly. I also updated the OAuth scope to https://docs.google.com/feeds/ as suggested.
The program is failing with an "OAuth error" message. When muteHttpExceptions is set to true, the message is "Failed to authenticate to service: google".
I guess this is a scope problem but I really can't see what I've done wrong. Naturally, I've tried a few other possibilities without luck.
I've included the code below. Commented code is the instruction that worked until this week.
function getSSAsExcel(ssID)
{
var format = "xls";
//var scope = "https://spreadsheets.google.com/feeds/";
var scope = "https://docs.google.com/feeds/";
var oauthConfig = UrlFetchApp.addOAuthService("google");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=" + scope);
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
var requestData = {
//"muteHttpExceptions": true,
"method": "GET",
"oAuthServiceName": "google",
"oAuthUseToken": "always"
};
//var url = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=" + ssID
var url = "https://docs.google.com/spreadsheets/d/" + ssID
+ "/feeds/download/spreadsheets/Export?"
+ "&size=A4" + "&portrait=true" +"&fitw=true" + "&exportFormat=" + format;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
return contents;
}
Thanks for your help!
Instead of using OAuthConfig (which must be auth'ed in the Script Editor) you can pass an OAuth2 token instead, retrievable via ScriptApp.getOAuthToken().
The code snippet below uses the Advanced Drive service to get the export URL, but if you hand construct the URL you'll need to ensure that the Drive scope is still requested by your script (simply include a call to DriveApp.getRootFolder() somewhere in your script code).
function exportAsExcel(spreadsheetId) {
var file = Drive.Files.get(spreadsheetId);
var url = file.exportLinks[MimeType.MICROSOFT_EXCEL];
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
return response.getBlob();
}

Is there a field for knowing if the youtube channel is verified from the Youtube API?

I am using the Youtube data API and I needed to know if there is any way of finding that the youtube channel is a Verified one.
just ran into this today, and while the channelBranding of the V3 youtube API looks promising, I couldn't get it to return if the account/channel user id was verified or not
so I threw up a pretty lame php script that uses DOM model searching to examine the html directly.
to return true if the following element is present.
<a href="//support.google.com/youtube/bin/answer.py?answer=3046484&hl=en" class="qualified-channel-title-badge" target="_blank">
As of today (9/8/2014) a verified user will return true..
<?php
function isVerified($youtubeUser)
{
$youtubeUser = trim($youtubeUser);
$url = '\''."https://www.youtube.com/user/".$youtubeUser.'\'';
$url = "https://www.youtube.com/user/".$youtubeUser ;
$Verified = false;
echo "<BR>looking at $url ";
$ch = curl_init();
$timeout = 10;
curl_setopt($ch, CURLOPT_URL, "$url");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$html = curl_exec($ch);
curl_close($ch);
$dom = new DOMDocument;
#$dom->loadHTML($html);
foreach ( $dom->getElementsByTagName('a') as $link ) {
$myVar = $link->getAttribute('class');
$search = "qualified-channel-title-badge";
$found=false;
$found = strpos($myVar, $search);
if ( $found !== false) {
$Verified = true; //echo "<BR><font color=green>TRUE</font>";
} else {
$Verified = false; //echo "<BR><font color=red>FALSE</font>";
}
}
if ( $Verified ) {
return true;
} else {
return false;
}
}
?>
Bye for now!
RE: mpgn's solution, note that there's a distinction between whether the G+ account is Verified and whether one or more of the accounts YouTube channels are Verified. It's possible for an account to have more than one channel, and each of those channels are verified independently, and for channels to be unverified even though the associated G+ account is verified.
As #Paul Blakely suggests, the current best way to do this is to check the status.longUploadStatus flag, per https://developers.google.com/youtube/v3/docs/channels
As of November, 2022, the YouTube Data API provides no method for determining whether or not a given YouTube channel is or is not verified. Instead, the current approach that yields reliable results is to scrape the channel, and parse a bit of JSON, and search the resulting structure.
We'll start by loading the server response for a given channel. Below I have a channel ID hard-coded in as the id variable:
const id = 'UCFNTTISby1c_H-rm5Ww5rZg';
const response = await needle( 'get', `https://www.youtube.com/channel/${id}` );
With our response object, we should now proceed to check that a 200 OK was received, indicating there were no issues retrieving the page data, and that it is safe to proceed:
if ( response.statusCode === 200 ) {
// proceed to search for verification status
}
Within the block following the condition is where we can start to retrieve the initial data for the YouTube page. When serving a channel page, YouTube will also serve initial data for the channel itself, presumably to speed up delivery among other reasons.
We'll look for this initial data, parse it as JSON, and sift through the results:
const json = response.body.match( /ytInitialData = (.*?);<\/script>/ )[1];
const parsed = JSON.parse( json );
With our data parsed, we'll turn our attention now to one piece of the resulting structure, the c4TabbedHeaderRenderer property. This is where badges for the page (such as a verification badge) are stored. We'll also define a verifiedLabel, to explain what it is we're seeking:
const header = parsed.header.c4TabbedHeaderRenderer;
const verifiedLabel = 'BADGE_STYLE_TYPE_VERIFIED';
Lastly we need to confirm that badges is an array (it may not be, in the event the channel has no badges to enumerate), and follow that up with a check for our verifiedLabel badge:
const verified = Array.isArray(header.badges) && header.badges.some( badge => {
return badge.metadataBadgeRenderer.style === verifiedLabel
});
At this point, verified is either true (if the channel is verified), or false. I hope this helps!
On verified channels, the class "has-badge" is present.
Work in 2018:
<?php
$key = 'has-badge';
$channel = file_get_contents('https://www.youtube.com/...');
if( stripos($channel, $key) !== FALSE )
echo "Verified";
else
echo "Not Verified";
?>
If may be possible to check infer the verified status of a youtube channel via the status.longUploadsStatus flag being either allowed or eligible, as currently this feature requires the associated youtube account to be verified.
source : https://developers.google.com/youtube/v3/docs/channels

Twitter - sign request fail

I'm trying to get a request signed with twitter so I can get a request token and got stuck. I have used the info that twitter use in their documentation to be sure that I have formated t correctly etc. I have identical Basestring and Key but still I'm not getting the same Signature. I have looked at several other examples and I seem to have done the same thing.
Would love some help to sort this out!
Here is the code:
private function sign_request($http_method, $url, $params, $oath)
{
// SET BASE STRING
$sign_params = $this->set_sign_params($params, $oath);
$sign_url = $this->set_sign_url($url);
$base_string = $this->set_sign_basestring($http_method, $sign_params, $sign_url);
print $base_string; // Output the same as the twitter example: POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3Dhttp%3A%2F%2Flocalhost%3A3005%2Fthe_dance%2Fprocess_callback%3Fservice_provider_id%3D11%26oauth_consumer_key%3DGDdmIQH6jhtmLUypg82g%26oauth_nonce%3DQP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1272323042%26oauth_version%3D1.0
// GET HMAC-SHA1 SIGNATURE
if($this->signature_method == 'HMAC-SHA1')
{
// SET KEY
$key = $this->set_sign_key();
print $key; // Output the same as the twitter example: MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98&
//SIGN
$signature = base64_encode(hash_hmac('sha1', $base_string, $key, true));
print $signature; // DO NOT output the same as the twitter example. Twitteroutput: 8wUi7m5HFQy76nowoCThusfgB+Q= and my outout: Ewqbgi+AMRZGMcqwQTjhE5/ZD80=
}
return $signature;
}
What have I missed? Anyone got any Idea?
Also a "fun" thing is that if I set the signture to the one in the twitter example I still can't get a request token...
Thanks in advanced!
Your base string is not the same as Twitter's. That is why you are getting different signatures.
Twitter's:
POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Flocalhost%253A3005%252Fthe_dance%252Fprocess_callback%253Fservice_provider_id%253D11%26oauth_consumer_key%3DGDdmIQH6jhtmLUypg82g%26oauth_nonce%3DQP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1272323042%26oauth_version%3D1.0
Your's:
POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3Dhttp%3A%2F%2Flocalhost%3A3005%2Fthe_dance%2Fprocess_callback%3Fservice_provider_id%3D11%26oauth_consumer_key%3DGDdmIQH6jhtmLUypg82g%26oauth_nonce%3DQP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1272323042%26oauth_version%3D1.0
The difference is in the oauth_callback variable.
Twitter's:
oauth_callback%3Dhttp%253A%252F%252Flocalhost%253A3005%252Fthe_dance%252Fprocess_callback%253Fservice_provider_id%253D11%26
Your's:
oauth_callback%3Dhttp%3A%2F%2Flocalhost%3A3005%2Fthe_dance%2Fprocess_callback%3Fservice_provider_id%3D11%26

Resources