I'm looking to write the perfect code for translating messages formatted for WhatsApp into messages formatted for Telegram.
Whatsapp uses * and _ for bold and italic (but if you dive into it you'll discover that the parsing rules are quite elaborate): https://faq.whatsapp.com/general/chats/how-to-format-your-messages/?lang=en
Telegram uses HTML tags: https://sendpulse.com/knowledge-base/chatbot/format-text
I've used this answer to create the following code. It works but fails to convert correctly in some cases i.e. when there is a solitary *.
function whatsapp2Telegram(WAtxt) {
var TelegramText = WAtxt
const htmlFormat = [{
symbol: '*',
tag: 'b'
},
{
symbol: '_',
tag: 'i'
},
{
symbol: '~',
tag: 'pre'
},
{
symbol: '```',
tag: 'code'
},
];
htmlFormat.forEach(({
symbol,
tag
}) => {
if (!TelegramText) return;
const regex = new RegExp(`\\${symbol}([^${symbol}]*)\\${symbol}`, 'gm');
const match = TelegramText.match(regex);
if (!match) return;
match.forEach(m => {
let formatted = m;
for (let i = 0; i < 2; i++) {
formatted = formatted.replace(symbol, `<${i > 0 ? '/' : ''}${tag}>`);
}
TelegramText = TelegramText.replace(m, formatted);
});
});
return TelegramText
}
Related
I am trying to grab some json data to display in Ui but when I iterate over it using the map method I keep getting undefined.Any help will be really appreciated.Here is a link on code sandbox https://codesandbox.io/s/late-wood-kx8w2?file=/src/App.js
This line
const [items, setItem] = useState(Object.keys(trees));
is passing the tree keys to the View function and not the actual data. I believe that you meant to pass the data. Your code passes 'name' and 'children' as {items} that then gets displayed by View.js.
The following code shows you how you can parse the tree and get the names and the values. It's incomplete, but it should give you a start on how to do the traversal.
import React, { useState } from "react";
export default function Start(){
const trees = {
name: "root",
children: [
{
name: "child1",
children: [
{ name: "child1-child1", data: "c1-c1 Hello" },
{ name: "child1-child2", data: "c1-c2 JS" }
]
},
{ name: "child2", data: "c2 World" }
]
};
const treesCopy = trees;
function Traverse(tree){
var treesCopy = tree;
var str = [];
for (var prop in treesCopy) {
console.log(prop);
if (prop=="children"){
str = str + "name: "+ prop + ",";
treesCopy = treesCopy[prop][0];
// console.log('New tree: ',treesCopy);
return str + Traverse(treesCopy);
}
str = str + "name: "+ prop +" value: " + treesCopy[prop]+",";
}
return str;
};
const str = Traverse(treesCopy);
return(
<>
{
str ? str.split(",").map(place => <p> {place} </p>)
: ""
}
</>
)
}
I have made Custom Fields in my Users in Google Suite.
Category: Foresatt
Among them:
Name: 'foresatt epost', type:email, number: multiple values
I would like to list these values using Google Script. I used this:
https://developers.google.com/admin-sdk/directory/v1/quickstart/apps-script
To write this code:
function listUsers() {
var optionalArgs = {
customer: 'my_customer',
maxResults: 10,
orderBy: 'email',
projection: 'custom',
customFieldMask:'Foresatt'
};
var response = AdminDirectory.Users.list(optionalArgs);
var users = response.users;
if (users && users.length > 0) {
Logger.log('Users:');
for (i = 0; i < users.length; i++) {
var user = users[i];
var foresatt = user.customSchemas;
Logger.log('%s (%s)', user.primaryEmail, user.name.fullName, foresatt);
}
} else {
Logger.log('No users found.');
}
}
That works, but I would like to get only the values. What I get now:
{Foresatt={
foresatt_mob=[{value=X#X#X#X#, type=work}, {type=work, value=X#X#X#X#}, {type=work, value=X#X#X#X#}],
foresatt_epost=[{value=xx#xx.no, type=work}, {type=work, value=xy#xx.no}, {value=yy#xx.no, type=work}],
foresatt_navn=[{type=work, value=Xx}, {value=Xy, type=work}, {type=work, value=Yy}]
}
}
What I would like to get: xx#xx.no, xy#xx.no, yy#xx.no
I have tried several things, but I'm afraid I'm not experienced enough.
var epost = foresatt.foresatt_epost;
Results in: TypeError: Cannot read property 'foresatt_epost'
var epost = foresatt('foresatt_epost');
Results in: TypeError: foresatt is not a function
Please advise me, how do I get only the values fram the field 'foresatt epost'?
I believe your goal as follows.
You want to retrieve the values of xx#xx.no, xy#xx.no, yy#xx.no from the following object:
const object = {
Foresatt: {
foresatt_mob: [
{ value: "X#X#X#X#",type: "work"},
{ value: "X#X#X#X#",type: "work"},
{ value: "X#X#X#X#",type: "work"},
],
foresatt_epost: [
{ value: "xx#xx.no", type: "work"},
{ value: "xy#xx.no", type: "work"},
{ value: "yy#xx.no", type: "work"},
],
foresatt_navn: [
{ type: "work", value: "Xx"},
{ type: "work", value: "Xy"},
{ type: "work", value: "Yy"},
]
}
}
In this case, the values can be retrieved from the object.Foresatt.foresatt_epost array.
Sample script:
const object = {}; //Your object
const res = object.Foresatt.foresatt_epost.map(e => e.value);
console.log(res) // Outputs: [ 'xx#xx.no', 'xy#xx.no', 'yy#xx.no' ]
If user.customSchemas is the above object, the script is as follows.
var foresatt = user.customSchemas;
const res = foresatt.Foresatt.foresatt_epost.map(e => e.value);
console.log(res)
If you want to retrieve the value as a comma separated string, you can use res.join(",").
References:
map()
Note:
If there is no guarantee your property will exist in your object, you can do (object.property||[]).map(...) instead of object.property.map(...) to avoid the error Uncaught TypeError: Cannot read property 'forEach' of undefined.
This is the html string and i want to print it in pdfmake
let html_string = "<html><head></head><body><p>HI</p></body></html>";
//something like this
{ text: html_string,
pageBreak: 'after',
},
it should print as a html content in a part of pdfmake: how to print string containing html as it is in pdf .
Option 1. Convert the html to string before passing it to pdfmake. You can use html-to-text
.
const PdfPrinter = require("pdfmake");
const htmlToText = require('html-to-text');
let dd = {
pageSize: "A4",
pageOrientation: "portrait",
content: [
{
text: htmlToText.fromString("<p>Hello <strong>World</strong></p>", {
wordwrap: 130
}),
style: "",
}
],
}
let printer = new PdfPrinter(fonts);
let doc = printer.createPdfKitDocument(dd);
Option 2. Use html-to-pdfmake
. You will have to add jsdom if you are doing it in Nodejs side.
const PdfPrinter = require("pdfmake");
let jsdom = require("jsdom");
let { JSDOM } = jsdom;
let { window } = new JSDOM("");
const htmlToPdfmake = require("html-to-pdfmake");
let dd = {
pageSize: "A4",
pageOrientation: "portrait",
content: [
{
text: htmlToPdfmake(salesConditions.salesConditionBody, {
window: window,
}),
style: "",
}
],
}
let printer = new PdfPrinter(fonts);
let doc = printer.createPdfKitDocument(dd);
Use a html parser to get the html content you want. https://www.npmjs.com/package/node-html-parser
After that, i would write an object build function to get the correct html tag content you're looking for.
import { parse } from 'node-html-parser';
const root = parse('<ul id="list"><li>Hello World</li></ul>');
var htmlBody = root.querySelector('#list');
function getContentBuilder (htmlBody ) {
var record = {}
//Locate htmlBody childnode that you want and insert to record
return record;
}
//something like this
{ text: getContentBuilder(htmlBody) ,
pageBreak: 'after',
},
you can use HTML2PDF Js library to make pdf from html string.
check this link here
many JS libraies available in npm to create PDF from image or html.
I'm trying to read some test data from a local json file and output the data with correct formatting into a textarea. Right now though it just outputs [object Object]. How would I go about getting it so it outputs:
Id: theIdGoesHere
Title: theTitleGoesHere
step.service.ts The service used to call the json data
public getJson(): Observable<any>{
return this.http.get('/assets/jsonData/MyJson.json')
.map(response => response.json());
}
MyJson.json
{
"data":[
{
"id": 1,
"title":"Test1"
},
{
"id": 2,
"title":"Test2"
}
]
}
main.componenet.ts
private testVar: any;
test(){
this.stepService.getJson().subscribe(data => (this.testVar = data));
}
anothermethod(){
this.test();
this.mainStepText = this.testVar; //mainStepText binded to textarea with [(ngModel)]="mainStepText"
}
get mainStepText2() { //Rebinded this one
const text = [];
const { data } = this.testVar;
for (let item of this.testVar.data) {
Object.keys(item).forEach(key => {
text.push(key + ': ' + item[key]);
});
}
return text.join('\r\n'); // \r\n is the line break
}
You can use json pipe to format your object into a json string:
[(ngModel)]="mainStepText | json"
If you want to show a specific property of your object, you can access it in your template:
[(ngModel)]="mainStepText.data[0].title"
This will display "Test1" in your field.
You could loop through your json.data and through their keys to extract the text and values and generate the string you need for the text area.
const text = [];
for (let item of this.textVar.data) {
Object.keys(item).forEach(key => {
text.push(key + ': ' + item[key]);
});
}
return text.join('\r\n'); // \r\n is the line break
Here's the running code, I put it in app.ts: http://plnkr.co/edit/3AbQYQOW0MVBqO91X9qi?p=preview
Hope this is of help.
We are working with a 3rd party grid (telerik kendo) that has paging/sorting/filtering built in. It will send the requests in a certain way when making the GET call and I'm trying to determine if there is a way to translate these requests to AutoQuery friendly requests.
Query string params
Sort Pattern:
sort[{0}][field] and sort[{0}][dir]
Filtering:
filter[filters][{0}][field]
filter[filters][{0}][operator]
filter[filters][{0}][value]
So this which is populated in the querystring:
filter[filters][0][field]
filter[filters][0][operator]
filter[filters][0][value]
would need to be translated to.
FieldName=1 // filter[filters][0][field]+filter[filters][0][operator]+filter[filters][0][value] in a nutshell (not exactly true)
Should I manipulate the querystring object in a plugin by removing the filters (or just adding the ones I need) ? Is there a better option here?
I'm not sure there is a clean way to do this on the kendo side either.
I will explain the two routes I'm going down, I hope to see a better answer.
First, I tried to modify the querystring in a request filter, but could not. I ended up having to run the autoqueries manually by getting the params and modifying them before calling AutoQuery.Execute. Something like this:
var requestparams = Request.ToAutoQueryParams();
var q = AutoQueryDb.CreateQuery(requestobject, requestparams);
AutoQueryDb.Execute(requestobject, q);
I wish there was a more global way to do this. The extension method just loops over all the querystring params and adds the ones that I need.
After doing the above work, I wasn't very happy with the result so I investigated doing it differently and ended up with the following:
Register the Kendo grid filter operations to their equivalent Service Stack auto query ones:
var aq = new AutoQueryFeature { MaxLimit = 100, EnableAutoQueryViewer=true };
aq.ImplicitConventions.Add("%neq", aq.ImplicitConventions["%NotEqualTo"]);
aq.ImplicitConventions.Add("%eq", "{Field} = {Value}");
Next, on the grid's read operation, we need to reformat the the querystring:
read: {
url: "/api/stuff?format=json&isGrid=true",
data: function (options) {
if (options.sort && options.sort.length > 0) {
options.OrderBy = (options.sort[0].dir == "desc" ? "-" : "") + options.sort[0].field;
}
if (options.filter && options.filter.filters.length > 0) {
for (var i = 0; i < options.filter.filters.length; i++) {
var f = options.filter.filters[i];
console.log(f);
options[f.field + f.operator] = f.value;
}
}
}
Now, the grid will send the operations in a Autoquery friendly manner.
I created an AutoQueryDataSource ts class that you may or may not find useful.
It's usage is along the lines of:
this.gridDataSource = AutoQueryKendoDataSource.getDefaultInstance<dtos.QueryDbSubclass, dtos.ListDefinition>('/api/autoQueryRoute', { orderByDesc: 'createdOn' });
export default class AutoQueryKendoDataSource<queryT extends dtos.QueryDb_1<T>, T> extends kendo.data.DataSource {
private constructor(options: kendo.data.DataSourceOptions = {}, public route?: string, public request?: queryT) {
super(options)
}
defer: ng.IDeferred<any>;
static exportToExcel(columns: kendo.ui.GridColumn[], dataSource: kendo.data.DataSource, filename: string) {
let rows = [{ cells: columns.map(d => { return { value: d.field }; }) }];
dataSource.fetch(function () {
var data = this.data();
for (var i = 0; i < data.length; i++) {
//push single row for every record
rows.push({
cells: _.map(columns, d => { return { value: data[i][d.field] } })
})
}
var workbook = new kendo.ooxml.Workbook({
sheets: [
{
columns: _.map(columns, d => { return { autoWidth: true } }),
// Title of the sheet
title: filename,
// Rows of the sheet
rows: rows
}
]
});
//save the file as Excel file with extension xlsx
kendo.saveAs({ dataURI: workbook.toDataURL(), fileName: filename });
})
}
static getDefaultInstance<queryT extends dtos.QueryDb_1<T>, T>(route: string, request: queryT, $q?: ng.IQService, model?: any) {
let sortInfo: {
orderBy?: string,
orderByDesc?: string,
skip?: number
} = {
};
let opts = {
transport: {
read: {
url: route,
dataType: 'json',
data: request
},
parameterMap: (data, type) => {
if (type == 'read') {
if (data.sort) {
data.sort.forEach((s: any) => {
if (s.field.indexOf('.') > -1) {
var arr = _.split(s.field, '.')
s.field = arr[arr.length - 1];
}
})
}//for autoquery to work, need only field names not entity names.
sortInfo = {
orderByDesc: _.join(_.map(_.filter(data.sort, (s: any) => s.dir == 'desc'), 'field'), ','),
orderBy: _.join(_.map(_.filter(data.sort, (s: any) => s.dir == 'asc'), 'field'), ','),
skip: 0
}
if (data.page)
sortInfo.skip = (data.page - 1) * data.pageSize,
_.extend(data, request);
//override sorting if done via grid
if (sortInfo.orderByDesc) {
(<any>data).orderByDesc = sortInfo.orderByDesc;
(<any>data).orderBy = null;
}
if (sortInfo.orderBy) {
(<any>data).orderBy = sortInfo.orderBy;
(<any>data).orderByDesc = null;
}
(<any>data).skip = sortInfo.skip;
return data;
}
return data;
},
},
requestStart: (e: kendo.data.DataSourceRequestStartEvent) => {
let ds = <AutoQueryKendoDataSource<queryT, T>>e.sender;
if ($q)
ds.defer = $q.defer();
},
requestEnd: (e: kendo.data.DataSourceRequestEndEvent) => {
new DatesToStringsService().convert(e.response);
let ds = <AutoQueryKendoDataSource<queryT, T>>e.sender;
if (ds.defer)
ds.defer.resolve();
},
schema: {
data: (response: dtos.QueryResponse<T>) => {
return response.results;
},
type: 'json',
total: 'total',
model: model
},
pageSize: request.take || 40,
page: 1,
serverPaging: true,
serverSorting: true
}
let ds = new AutoQueryKendoDataSource<queryT, T>(opts, route, request);
return ds;
}
}