2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 16:56:54 +00:00

50_Signalbot: Added support for unicode textformatting and emoticons

git-svn-id: https://svn.fhem.de/fhem/trunk@25638 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
Adimarantis 2022-02-06 14:21:21 +00:00
parent 885d68d66b
commit 5f2c9b0ae5
4 changed files with 239 additions and 208 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it. # Do not insert empty lines here, update check depends on it.
- feature: 50_Signalbot: text formatting and emoticons via unicode
- feature: 70_ESCVP21net.pm: toggle, TW7400, new Readings - feature: 70_ESCVP21net.pm: toggle, TW7400, new Readings
- new: lib/FHEM/Text/Unicode: apply text styles in Unicode - new: lib/FHEM/Text/Unicode: apply text styles in Unicode
- feature: 66_EseraMulti: added support for solar sensor Esera 11112 - feature: 66_EseraMulti: added support for solar sensor Esera 11112

View File

@ -1,6 +1,6 @@
############################################## ##############################################
#$Id$ #$Id$
my $Signalbot_VERSION="3.6"; my $Signalbot_VERSION="3.7";
# Simple Interface to Signal CLI running as Dbus service # Simple Interface to Signal CLI running as Dbus service
# Author: Adimarantis # Author: Adimarantis
# License: GPL # License: GPL
@ -27,6 +27,9 @@ use HttpUtils;
eval "use Protocol::DBus;1"; eval "use Protocol::DBus;1";
eval "use Protocol::DBus::Client;1" or my $DBus_missing = "yes"; eval "use Protocol::DBus::Client;1" or my $DBus_missing = "yes";
require FHEM::Text::Unicode;
use FHEM::Text::Unicode qw(:ALL);
#maybe really get introspective here instead of handwritten list #maybe really get introspective here instead of handwritten list
my %signatures = ( my %signatures = (
"setContactBlocked" => "sb", "setContactBlocked" => "sb",
@ -104,6 +107,7 @@ sub Signalbot_Initialize($) {
"cmdFavorite ". "cmdFavorite ".
"favorites:textField-long ". "favorites:textField-long ".
"autoJoin:yes,no ". "autoJoin:yes,no ".
"formatting:none,html,markdown,both ".
"registerMethod:SMS,Voice ". "registerMethod:SMS,Voice ".
"$readingFnAttributes"; "$readingFnAttributes";
} }
@ -339,7 +343,7 @@ sub Signalbot_Set($@) { #
eval { $fullstring=decode_utf8($fullstring); }; eval { $fullstring=decode_utf8($fullstring); };
Log3 $hash->{NAME}, 3 , $hash->{NAME}.": Error from decode" if $@; Log3 $hash->{NAME}, 3 , $hash->{NAME}.": Error from decode" if $@;
Log3 $hash->{NAME}, 3 , $hash->{NAME}.": Before parse:" . encode_utf8($fullstring) . ":"; Log3 $hash->{NAME}, 3 , $hash->{NAME}.": Before parse:" .$fullstring. ":";
my $tmpmessage = $fullstring =~ s/\\n/\x0a/rg; my $tmpmessage = $fullstring =~ s/\\n/\x0a/rg;
my @args=parse_line(' ',0,$tmpmessage); my @args=parse_line(' ',0,$tmpmessage);
@ -401,7 +405,7 @@ sub Signalbot_Set($@) { #
my @newatt; my @newatt;
foreach my $file (@attachments) { foreach my $file (@attachments) {
if ( -e $file ) { if ( -e $file ) {
if (! $file =~ /tmp\/signalbot/) { if ($file=~/^\/tmp\/signalbot.*/ ne 1) {
$file =~ /^.*?\.([^.]*)?$/; $file =~ /^.*?\.([^.]*)?$/;
my $type = $1; my $type = $1;
my $tmpfilename="/tmp/signalbot".gettimeofday().".".$type; my $tmpfilename="/tmp/signalbot".gettimeofday().".".$type;
@ -419,7 +423,11 @@ sub Signalbot_Set($@) { #
} }
@attachments=@newatt; @attachments=@newatt;
} }
#Convert html or markdown to unicode
my $format=AttrVal($hash->{NAME},"formatting","none");
my $convmsg=formatTextUnicode($format,$message);
$message=$convmsg if defined $convmsg;
#Send message to individuals (bulk) #Send message to individuals (bulk)
if (@recipients > 0) { if (@recipients > 0) {
Signalbot_sendMessage($hash,join(",",@recipients),join(",",@attachments),$message); Signalbot_sendMessage($hash,join(",",@recipients),join(",",@attachments),$message);
@ -452,7 +460,7 @@ sub Signalbot_Get($@) {
my $account = ReadingsVal($name,"account","none"); my $account = ReadingsVal($name,"account","none");
if ($cmd eq "?") { if ($cmd eq "?") {
my $gets="favorites:noArg accounts:noArg "; my $gets="favorites:noArg accounts:noArg helpUnicode:noArg ";
$gets.="contacts:all,nonblocked ". $gets.="contacts:all,nonblocked ".
"groups:all,active,nonblocked " if $account ne "none"; "groups:all,active,nonblocked " if $account ne "none";
return "Signalbot_Get: Unknown argument $cmd, choose one of ".$gets; return "Signalbot_Get: Unknown argument $cmd, choose one of ".$gets;
@ -464,6 +472,8 @@ sub Signalbot_Get($@) {
if ($cmd eq "introspective") { if ($cmd eq "introspective") {
my $reply=Signalbot_CallS($hash,"org.freedesktop.DBus.Introspectable.Introspect"); my $reply=Signalbot_CallS($hash,"org.freedesktop.DBus.Introspectable.Introspect");
return undef; return undef;
} elsif ($cmd eq "helpUnicode") {
return demoUnicodeHTML();
} elsif ($cmd eq "accounts") { } elsif ($cmd eq "accounts") {
my $num=Signalbot_getAccounts($hash); my $num=Signalbot_getAccounts($hash);
return "Error in listAccounts" if $num<0; return "Error in listAccounts" if $num<0;
@ -825,7 +835,7 @@ sub Signalbot_MessageReceived ($@) {
} }
} }
} }
Log3 $hash->{NAME}, 4, $hash->{NAME}.": Message from $sender : $message processed"; Log3 $hash->{NAME}, 4, $hash->{NAME}.": Message from $sender : ".decode_utf8($message)." processed";
} else { } else {
Log3 $hash->{NAME}, 2, $hash->{NAME}.": Ignored message due to allowedPeer by $source:$message"; Log3 $hash->{NAME}, 2, $hash->{NAME}.": Ignored message due to allowedPeer by $source:$message";
readingsSingleUpdate($hash, 'lastError', "Ignored message due to allowedPeer by $source:$message",1); readingsSingleUpdate($hash, 'lastError', "Ignored message due to allowedPeer by $source:$message",1);
@ -925,6 +935,8 @@ sub Signalbot_setup($@){
$hash->{STATE}="Connecting"; $hash->{STATE}="Connecting";
Signalbot_fetchFile($hash,"svn.fhem.de","/fhem/trunk/fhem/contrib/signal/signal_install.sh","www/signal/signal_install.sh"); Signalbot_fetchFile($hash,"svn.fhem.de","/fhem/trunk/fhem/contrib/signal/signal_install.sh","www/signal/signal_install.sh");
chmod 0755, "www/signal/signal_install.sh"; chmod 0755, "www/signal/signal_install.sh";
#Make sure Logfile looks ok with Unicode characters and does not raise "Wide character"
binmode(LOG,"encoding(UTF-8)");
return undef; return undef;
} }
@ -1424,7 +1436,7 @@ sub Signalbot_refreshGroups($@) {
sub Signalbot_sendMessage($@) { sub Signalbot_sendMessage($@) {
my ( $hash,$rec,$att,$mes ) = @_; my ( $hash,$rec,$att,$mes ) = @_;
Log3 $hash->{NAME}, 4, $hash->{NAME}.": sendMessage called for $rec:$att:".encode_utf8($mes); Log3 $hash->{NAME}, 4, $hash->{NAME}.": sendMessage called for $rec:$att:".$mes;
my @recorg= split(/,/,$rec); my @recorg= split(/,/,$rec);
my @attach=split(/,/,$att); my @attach=split(/,/,$att);
@ -2098,7 +2110,6 @@ sub Signalbot_OSRel() {
# -2 for Audio # -2 for Audio
# -3 for other media # -3 for other media
# and extension without dot as 2nd list element # and extension without dot as 2nd list element
sub Signalbot_IdentifyStream($$) { sub Signalbot_IdentifyStream($$) {
my ($hash, $msg) = @_; my ($hash, $msg) = @_;
@ -2286,6 +2297,11 @@ For German documentation see <a href="https://wiki.fhem.de/wiki/Signalbot">Wiki<
<a id="Signalbot-get-favorites"></a> <a id="Signalbot-get-favorites"></a>
Lists the defined favorites in the attribute "favorites" in a readable format<br> Lists the defined favorites in the attribute "favorites" in a readable format<br>
</li> </li>
<li><b>get helpUnicode</b><br>
<a id="Signalbot-get-helpUnicode"></a>
Opens a cheat sheet for all supported replacements to format text or add emoticons using html-like tags or markdown.<br>
<b>Note:</b> This functionality needs to be enabled using the "formatting" attribute.<br>
</li>
<br> <br>
</ul> </ul>
@ -2367,6 +2383,17 @@ For German documentation see <a href="https://wiki.fhem.de/wiki/Signalbot">Wiki<
<a id="Signalbot-attr-defaultPeer"></a> <a id="Signalbot-attr-defaultPeer"></a>
If <b>send</b> is used without a recipient, the message will send to this account or group(with #)<br> If <b>send</b> is used without a recipient, the message will send to this account or group(with #)<br>
</li> </li>
<li><b>formatting</b><br>
<a id="Signalbot-attr-formatting"></a>
The "formatting" attribute has the following four options that allow highlighting in Unicode:
<ul>
<li>none - no replacements </li>
<li>html - replacements are enabled here with HTML-type tags (e.g. for bold &lt;b&gt; is bold &lt;/b&gt;)</li>
<li>markdown - replacements are enabled by markdown-like tags (e.g. __for italic__) as well as emotics</li>
<li>both - both methods are possible here</li>
</ul>
To learn about the syntax how to use tags and markdown, use the get helpUnicode method. You can still also simply copy&paste Unicode text from other sources.
</li>
<br> <br>
</ul> </ul>
<br> <br>

View File

@ -626,6 +626,7 @@ lib/FHEM/Core/Timer/Register.pm Beta-User FHEM Development
lib/FHEM/SynoModules/API.pm DS_Starter Sonstiges lib/FHEM/SynoModules/API.pm DS_Starter Sonstiges
lib/FHEM/SynoModules/SMUtils.pm DS_Starter Sonstiges lib/FHEM/SynoModules/SMUtils.pm DS_Starter Sonstiges
lib/FHEM/SynoModules/ErrCodes.pm DS_Starter Sonstiges lib/FHEM/SynoModules/ErrCodes.pm DS_Starter Sonstiges
lib/FHEM/Text/Unicode.pm Adimarantis FHEM Development
contrib/sacha_gloor/* rudolfkoenig/orphan Sonstiges contrib/sacha_gloor/* rudolfkoenig/orphan Sonstiges
contrib/70_ONKYO_AVR_PULL.pm loredo (deprecated) contrib/70_ONKYO_AVR_PULL.pm loredo (deprecated)

View File

@ -1,200 +1,202 @@
################################################################ ################################################################
# $Id$ # $Id$
# Maintainer: Adimarantis # Maintainer: Adimarantis
# Library to convert ASCII into formatted Unicode and apply styles like bold or emoticons # Library to convert ASCII into formatted Unicode and apply styles like bold or emoticons
# #
# This script free software; you can redistribute it and/or modify # This script free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# The GNU General Public License can be found at # The GNU General Public License can be found at
# http://www.gnu.org/copyleft/gpl.html. # http://www.gnu.org/copyleft/gpl.html.
# A copy is found in the textfile GPL.txt and important notices to the license # A copy is found in the textfile GPL.txt and important notices to the license
# from the author is found in LICENSE.txt distributed with these scripts. # from the author is found in LICENSE.txt distributed with these scripts.
# #
# This script is distributed in the hope that it will be useful, # This script is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
################################################################ ################################################################
package FHEM::Text::Unicode; package FHEM::Text::Unicode;
use strict; use strict;
use warnings; use warnings;
use Exporter 'import'; use Exporter 'import';
our @EXPORT_OK = qw (formatTextUnicode formatStringUnicode demoUnicode demoUnicodeHTML); our @EXPORT_OK = qw (formatTextUnicode formatStringUnicode demoUnicode demoUnicodeHTML);
our %EXPORT_TAGS = (ALL => [@EXPORT_OK]); our %EXPORT_TAGS = (ALL => [@EXPORT_OK]);
#define globally for demo #define globally for demo
#Emoticons #Emoticons
my @mrep = ( my @mrep = (
[":\\)","\x{1F600}"], [":\\)","\x{1F600}"],
[":-\\)","\x{1F600}"], [":-\\)","\x{1F600}"],
[":\\(","\x{1F641}"], [":\\(","\x{1F641}"],
["<3","\x{2665}"], ["<3","\x{2665}"],
[";-\\)","\x{1F609}"], [";-\\)","\x{1F609}"],
[":\\+1:","\x{1F44D}"], [":\\+1:","\x{1F44D}"],
[":smile:","\x{1F600}"], [":smile:","\x{1F600}"],
[":sad:","\x{1F641}"], [":sad:","\x{1F641}"],
[":heart:","\x{2665}"], [":heart:","\x{2665}"],
[":wink:","\x{1F609}"], [":wink:","\x{1F609}"],
[":thumbsup:","\x{1F44D}"], [":thumbsup:","\x{1F44D}"],
); );
#html like styles #html like styles
my @htags = ( my @htags = (
["bold" ,"<b>","</b>"], ["bold" ,"<b>","</b>"],
["italic","<i>","</i>"], ["italic","<i>","</i>"],
["bold-italic","<bi>","</bi>"], ["bold-italic","<bi>","</bi>"],
["mono","<tt>","</tt>"], ["mono","<tt>","</tt>"],
["mono","<code>","</code>"], ["mono","<code>","</code>"],
["underline","<u>","</u>"], ["underline","<u>","</u>"],
["strikethrough","<s>","</s>"], ["strikethrough","<s>","</s>"],
["fraktur","<fraktur>","</fraktur>"], ["fraktur","<fraktur>","</fraktur>"],
["script","<script>","</script>"], ["script","<script>","</script>"],
["square","<square>","</square>"], ["square","<square>","</square>"],
); );
#Single replacements in html mode #Single replacements in html mode
my @hrep = ( my @hrep = (
["<br>","\n"], ["<br>","\n"],
); );
#Markdown styles #Markdown styles
my @mtags = ( my @mtags = (
["italic","__","__"], ["italic","__","__"],
["strikethrough","~~","~~"], ["strikethrough","~~","~~"],
["bold","\\*\\*","\\*\\*"], ["bold","\\*\\*","\\*\\*"],
["mono","``","``"], ["mono","``","``"],
); );
#Convert text with Markdown/html to Unicode #Convert text with Markdown/html to Unicode
#Arguments: #Arguments:
#$format: #$format:
# html: Only apply HTML-like formatting like <x>....</x> # html: Only apply HTML-like formatting like <x>....</x>
# markdown: Only apply Markdown formatting like __text__ and emoticon replacements # markdown: Only apply Markdown formatting like __text__ and emoticon replacements
# both: Apply both formatting styles # both: Apply both formatting styles
#$msg: ASCII String that should be replaced #$msg: ASCII String that should be replaced
#return: Unicode string with applied replacements #returns: Unicode string with applied replacements
#To display all replacements use the demoUnicode() pr demoUnicodeHTML() function #To display all replacements use the demoUnicode() or demoUnicodeHTML() function
sub formatTextUnicode($$) { sub formatTextUnicode($$) {
my ($format,$msg) = @_; my ($format,$msg) = @_;
my @tags; my @tags;
my @reps; my @reps;
if ($format eq "markdown" || $format eq "both") { if ($format eq "markdown" || $format eq "both") {
push @tags, @mtags; push @tags, @mtags;
push @reps, @mrep; push @reps, @mrep;
} }
if ($format eq "html" || $format eq "both") { if ($format eq "html" || $format eq "both") {
push @tags, @htags; push @tags, @htags;
push @reps, @hrep; push @reps, @hrep;
} }
#First pass, replace singe special characters #First pass, replace singe special characters
foreach my $arr (@reps) { foreach my $arr (@reps) {
my @val=@$arr; my @val=@$arr;
$msg =~ s/$val[0]/$val[1]/sg; $msg =~ s/$val[0]/$val[1]/sg;
} }
my $found=1; my $found=1;
my $matches=0; my $matches=0;
my $text; my $text;
while ($found && $matches<100) { while ($found && $matches<100) {
$matches++; $matches++;
$found=0; $found=0;
foreach my $arr (@tags) { foreach my $arr (@tags) {
my @val=@$arr; my @val=@$arr;
$msg =~ /$val[1](.*?)$val[2]/s; $msg =~ /$val[1](.*?)$val[2]/s;
if (defined $1) { if (defined $1) {
$text=formatStringUnicode($val[0],$1); $text=formatStringUnicode($val[0],$1);
if (defined $text) { if (defined $text) {
$msg =~ s/$val[1].*?$val[2]/$text/s; $msg =~ s/$val[1].*?$val[2]/$text/s;
$found=1; $found=1;
} }
} }
} }
} }
return $msg; return $msg;
} }
#Converts normal ASCII into unicode with a special font or style #Converts normal ASCII into unicode with a special font or style
#$font: Style to be applied: underline, strikethrough, bold, italic, bold-italic, script, fraktur, square, mono #$font: Style to be applied: underline, strikethrough, bold, italic, bold-italic, script, fraktur, square, mono
#$str: ASCII String that should be converted #$str: ASCII String that should be converted
#returns: Unicode String with style applied #returns: Unicode String with style applied
sub formatStringUnicode($$) { sub formatStringUnicode($$) {
my ($font,$str) = @_; my ($font,$str) = @_;
if ($font eq "underline") { if ($font eq "underline") {
$str =~ s/./$&\x{332}/g; $str =~ s/./$&\x{332}/g;
return $str; return $str;
} }
if ($font eq "strikethrough") { if ($font eq "strikethrough") {
$str =~ s/./$&\x{336}/g; $str =~ s/./$&\x{336}/g;
return $str; return $str;
} }
my %uc = ( my %uc = (
"bold" => [0x1d41a,0x1d400,0x1d7ce], "bold" => [0x1d41a,0x1d400,0x1d7ce],
"italic" => [0x1d44e,0x1d434,0x30], "italic" => [0x1d44e,0x1d434,0x30],
"bold-italic" => [0x1d482,0x1d468,0x30], "bold-italic" => [0x1d482,0x1d468,0x30],
"script" => [0x1d4ea,0x1d4d0,0x30], #Using boldface since normal misses some letters "script" => [0x1d4ea,0x1d4d0,0x30], #Using boldface since normal misses some letters
"fraktur" => [0x1d586,0x1d56c,0x30],#Using boldface since normal misses some letters "fraktur" => [0x1d586,0x1d56c,0x30],#Using boldface since normal misses some letters
"square" => [0x1f130,0x1f130,0x30], "square" => [0x1f130,0x1f130,0x30],
"mono" => [0x1d68a,0x1d670,0x30], "mono" => [0x1d68a,0x1d670,0x30],
); );
return undef if (! defined $uc{$font}); return undef if (! defined $uc{$font});
my $rep=chr($uc{$font}[0])."-".chr($uc{$font}[0]+25).chr($uc{$font}[1])."-".chr($uc{$font}[1]+25).chr($uc{$font}[2])."-".chr($uc{$font}[2]+9); my $rep=chr($uc{$font}[0])."-".chr($uc{$font}[0]+25).chr($uc{$font}[1])."-".chr($uc{$font}[1]+25).chr($uc{$font}[2])."-".chr($uc{$font}[2]+9);
$_=$str; $_=$str;
eval "tr/a-zA-Z0-9/$rep/"; #"no warnings" to prevent a bug in older Perl versions (seen in 5.28) that warns about
return undef if $@; #"Replacement list is longer than search list" when using ASCII->Unicode replacements
#Special handling for characters missing in some fonts eval "{no warnings; tr/a-zA-Z0-9/$rep/}";
# 0x1d455 => 0x1d629, #italic h -> italic sans-serif h or 0x210e (planck constant) return undef if $@;
# 0x1d4ba => 0x1d452, #script e -> serif e (not used -> using bold script charset which is complete #Special handling for characters missing in some fonts
$_ =~ tr/\x{1d455}\x{1d4ba}/\x{1d629}\x{1d452}/; # 0x1d455 => 0x1d629, #italic h -> italic sans-serif h or 0x210e (planck constant)
return $_; # 0x1d4ba => 0x1d452, #script e -> serif e (not used -> using bold script charset which is complete
} $_ =~ tr/\x{1d455}\x{1d4ba}/\x{1d629}\x{1d452}/;
return $_;
# Returns a String that is can be embedded in HTML (e.g. FHEM "get") and showcases all possible replacements and their syntax }
sub demoUnicodeHTML {
my $str=demoUnicode(); # Returns a String that is can be embedded in HTML (e.g. FHEM "get") and showcases all possible replacements and their syntax
$str =~ s/</&lt/sg; sub demoUnicodeHTML {
$str =~ s/</&gt/sg; my $str=demoUnicode();
$str =~ s/\n/<br>/sg; $str =~ s/</&lt/sg;
return $str; $str =~ s/</&gt/sg;
} $str =~ s/\n/<br>/sg;
return $str;
# Returns a printable String that showcases all possible replacements and their syntax }
sub demoUnicode {
my $str; # Returns a printable String that showcases all possible replacements and their syntax
$str.="HTML style formatting:\n"; sub demoUnicode {
foreach my $arr (@htags) { my $str;
my @val=@$arr; $str.="HTML style formatting:\n";
$str .= formatStringUnicode($val[0],$val[0]." TEXT 123").": $val[1]text$val[2]\n"; foreach my $arr (@htags) {
} my @val=@$arr;
$str.="newline: <br>\n"; $str .= formatStringUnicode($val[0],$val[0]." TEXT 123").": $val[1]text$val[2]\n";
}
$str.="\nMarkdown style formatting:\n"; $str.="newline: <br>\n";
foreach my $arr (@mtags) {
my @val=@$arr; $str.="\nMarkdown style formatting:\n";
my $md= formatStringUnicode($val[0],$val[0]." TEXT 123").": $val[1]text$val[2]\n"; foreach my $arr (@mtags) {
$md =~ s/\\//g; my @val=@$arr;
$str.=$md; my $md= formatStringUnicode($val[0],$val[0]." TEXT 123").": $val[1]text$val[2]\n";
} $md =~ s/\\//g;
my $i=0; $str.=$md;
foreach my $arr (@mrep) { }
my @val=@$arr; my $i=0;
my $emo=$val[0]; foreach my $arr (@mrep) {
$emo =~ s/\\//g; my @val=@$arr;
$str.="$val[1]=$emo "; my $emo=$val[0];
$i++; $emo =~ s/\\//g;
if ($i>5) { $str.="$val[1]=$emo ";
$str.="\n"; $i++;
$i=0; if ($i>5) {
} $str.="\n";
} $i=0;
return $str; }
} }
return $str;
1; }
1;