From 5f2c9b0ae519901c2218db8786935d4af285b9da Mon Sep 17 00:00:00 2001 From: Adimarantis <> Date: Sun, 6 Feb 2022 14:21:21 +0000 Subject: [PATCH] 50_Signalbot: Added support for unicode textformatting and emoticons git-svn-id: https://svn.fhem.de/fhem/trunk@25638 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/50_Signalbot.pm | 43 +++- fhem/MAINTAINER.txt | 1 + fhem/lib/FHEM/Text/Unicode.pm | 402 +++++++++++++++++----------------- 4 files changed, 239 insertions(+), 208 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 358e2ef54..e33accc25 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # 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. + - feature: 50_Signalbot: text formatting and emoticons via unicode - feature: 70_ESCVP21net.pm: toggle, TW7400, new Readings - new: lib/FHEM/Text/Unicode: apply text styles in Unicode - feature: 66_EseraMulti: added support for solar sensor Esera 11112 diff --git a/fhem/FHEM/50_Signalbot.pm b/fhem/FHEM/50_Signalbot.pm index 8ae8c4360..5d1b052fe 100755 --- a/fhem/FHEM/50_Signalbot.pm +++ b/fhem/FHEM/50_Signalbot.pm @@ -1,6 +1,6 @@ ############################################## #$Id$ -my $Signalbot_VERSION="3.6"; +my $Signalbot_VERSION="3.7"; # Simple Interface to Signal CLI running as Dbus service # Author: Adimarantis # License: GPL @@ -27,6 +27,9 @@ use HttpUtils; eval "use Protocol::DBus;1"; 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 my %signatures = ( "setContactBlocked" => "sb", @@ -104,6 +107,7 @@ sub Signalbot_Initialize($) { "cmdFavorite ". "favorites:textField-long ". "autoJoin:yes,no ". + "formatting:none,html,markdown,both ". "registerMethod:SMS,Voice ". "$readingFnAttributes"; } @@ -339,7 +343,7 @@ sub Signalbot_Set($@) { # eval { $fullstring=decode_utf8($fullstring); }; 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 @args=parse_line(' ',0,$tmpmessage); @@ -401,7 +405,7 @@ sub Signalbot_Set($@) { # my @newatt; foreach my $file (@attachments) { if ( -e $file ) { - if (! $file =~ /tmp\/signalbot/) { + if ($file=~/^\/tmp\/signalbot.*/ ne 1) { $file =~ /^.*?\.([^.]*)?$/; my $type = $1; my $tmpfilename="/tmp/signalbot".gettimeofday().".".$type; @@ -419,7 +423,11 @@ sub Signalbot_Set($@) { # } @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) if (@recipients > 0) { Signalbot_sendMessage($hash,join(",",@recipients),join(",",@attachments),$message); @@ -452,7 +460,7 @@ sub Signalbot_Get($@) { my $account = ReadingsVal($name,"account","none"); if ($cmd eq "?") { - my $gets="favorites:noArg accounts:noArg "; + my $gets="favorites:noArg accounts:noArg helpUnicode:noArg "; $gets.="contacts:all,nonblocked ". "groups:all,active,nonblocked " if $account ne "none"; return "Signalbot_Get: Unknown argument $cmd, choose one of ".$gets; @@ -464,6 +472,8 @@ sub Signalbot_Get($@) { if ($cmd eq "introspective") { my $reply=Signalbot_CallS($hash,"org.freedesktop.DBus.Introspectable.Introspect"); return undef; + } elsif ($cmd eq "helpUnicode") { + return demoUnicodeHTML(); } elsif ($cmd eq "accounts") { my $num=Signalbot_getAccounts($hash); 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 { 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); @@ -925,6 +935,8 @@ sub Signalbot_setup($@){ $hash->{STATE}="Connecting"; 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"; + #Make sure Logfile looks ok with Unicode characters and does not raise "Wide character" + binmode(LOG,"encoding(UTF-8)"); return undef; } @@ -1424,7 +1436,7 @@ sub Signalbot_refreshGroups($@) { sub Signalbot_sendMessage($@) { 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 @attach=split(/,/,$att); @@ -2098,7 +2110,6 @@ sub Signalbot_OSRel() { # -2 for Audio # -3 for other media # and extension without dot as 2nd list element - sub Signalbot_IdentifyStream($$) { my ($hash, $msg) = @_; @@ -2286,6 +2297,11 @@ For German documentation see Wiki< Lists the defined favorites in the attribute "favorites" in a readable format
+
  • get helpUnicode
    + + Opens a cheat sheet for all supported replacements to format text or add emoticons using html-like tags or markdown.
    + Note: This functionality needs to be enabled using the "formatting" attribute.
    +

  • @@ -2367,6 +2383,17 @@ For German documentation see Wiki< If send is used without a recipient, the message will send to this account or group(with #)
    +
  • formatting
    + + The "formatting" attribute has the following four options that allow highlighting in Unicode: + + 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. +


  • diff --git a/fhem/MAINTAINER.txt b/fhem/MAINTAINER.txt index 4a8898287..875d5a0bf 100644 --- a/fhem/MAINTAINER.txt +++ b/fhem/MAINTAINER.txt @@ -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/SMUtils.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/70_ONKYO_AVR_PULL.pm loredo (deprecated) diff --git a/fhem/lib/FHEM/Text/Unicode.pm b/fhem/lib/FHEM/Text/Unicode.pm index e61a843a7..5ce8fc38b 100755 --- a/fhem/lib/FHEM/Text/Unicode.pm +++ b/fhem/lib/FHEM/Text/Unicode.pm @@ -1,200 +1,202 @@ -################################################################ -# $Id$ -# Maintainer: Adimarantis -# 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 -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# The GNU General Public License can be found at -# http://www.gnu.org/copyleft/gpl.html. -# 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. -# -# This script is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -################################################################ - -package FHEM::Text::Unicode; -use strict; -use warnings; -use Exporter 'import'; -our @EXPORT_OK = qw (formatTextUnicode formatStringUnicode demoUnicode demoUnicodeHTML); -our %EXPORT_TAGS = (ALL => [@EXPORT_OK]); - -#define globally for demo -#Emoticons -my @mrep = ( - [":\\)","\x{1F600}"], - [":-\\)","\x{1F600}"], - [":\\(","\x{1F641}"], - ["<3","\x{2665}"], - [";-\\)","\x{1F609}"], - [":\\+1:","\x{1F44D}"], - [":smile:","\x{1F600}"], - [":sad:","\x{1F641}"], - [":heart:","\x{2665}"], - [":wink:","\x{1F609}"], - [":thumbsup:","\x{1F44D}"], - ); -#html like styles -my @htags = ( - ["bold" ,"",""], - ["italic","",""], - ["bold-italic","",""], - ["mono","",""], - ["mono","",""], - ["underline","",""], - ["strikethrough","",""], - ["fraktur","",""], - ["script",""], - ["square","",""], -); -#Single replacements in html mode -my @hrep = ( - ["
    ","\n"], -); -#Markdown styles -my @mtags = ( - ["italic","__","__"], - ["strikethrough","~~","~~"], - ["bold","\\*\\*","\\*\\*"], - ["mono","``","``"], -); - -#Convert text with Markdown/html to Unicode -#Arguments: -#$format: -# html: Only apply HTML-like formatting like .... -# markdown: Only apply Markdown formatting like __text__ and emoticon replacements -# both: Apply both formatting styles -#$msg: ASCII String that should be replaced -#return: Unicode string with applied replacements -#To display all replacements use the demoUnicode() pr demoUnicodeHTML() function -sub formatTextUnicode($$) { - my ($format,$msg) = @_; - my @tags; - my @reps; - - if ($format eq "markdown" || $format eq "both") { - push @tags, @mtags; - push @reps, @mrep; - } - if ($format eq "html" || $format eq "both") { - push @tags, @htags; - push @reps, @hrep; - } - - #First pass, replace singe special characters - foreach my $arr (@reps) { - my @val=@$arr; - $msg =~ s/$val[0]/$val[1]/sg; - } - - my $found=1; - my $matches=0; - my $text; - while ($found && $matches<100) { - $matches++; - $found=0; - foreach my $arr (@tags) { - my @val=@$arr; - $msg =~ /$val[1](.*?)$val[2]/s; - if (defined $1) { - $text=formatStringUnicode($val[0],$1); - if (defined $text) { - $msg =~ s/$val[1].*?$val[2]/$text/s; - $found=1; - } - } - } - } - return $msg; -} - -#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 -#$str: ASCII String that should be converted -#returns: Unicode String with style applied -sub formatStringUnicode($$) { - my ($font,$str) = @_; - - if ($font eq "underline") { - $str =~ s/./$&\x{332}/g; - return $str; - } - if ($font eq "strikethrough") { - $str =~ s/./$&\x{336}/g; - return $str; - } - - my %uc = ( - "bold" => [0x1d41a,0x1d400,0x1d7ce], - "italic" => [0x1d44e,0x1d434,0x30], - "bold-italic" => [0x1d482,0x1d468,0x30], - "script" => [0x1d4ea,0x1d4d0,0x30], #Using boldface since normal misses some letters - "fraktur" => [0x1d586,0x1d56c,0x30],#Using boldface since normal misses some letters - "square" => [0x1f130,0x1f130,0x30], - "mono" => [0x1d68a,0x1d670,0x30], - ); - - 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); - $_=$str; - eval "tr/a-zA-Z0-9/$rep/"; - return undef if $@; -#Special handling for characters missing in some fonts -# 0x1d455 => 0x1d629, #italic h -> italic sans-serif h or 0x210e (planck constant) -# 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(); - $str =~ s//sg; - return $str; -} - -# Returns a printable String that showcases all possible replacements and their syntax -sub demoUnicode { - my $str; - $str.="HTML style formatting:\n"; - foreach my $arr (@htags) { - my @val=@$arr; - $str .= formatStringUnicode($val[0],$val[0]." TEXT 123").": $val[1]text$val[2]\n"; - } - $str.="newline:
    \n"; - - $str.="\nMarkdown style formatting:\n"; - foreach my $arr (@mtags) { - my @val=@$arr; - my $md= formatStringUnicode($val[0],$val[0]." TEXT 123").": $val[1]text$val[2]\n"; - $md =~ s/\\//g; - $str.=$md; - } - my $i=0; - foreach my $arr (@mrep) { - my @val=@$arr; - my $emo=$val[0]; - $emo =~ s/\\//g; - $str.="$val[1]=$emo "; - $i++; - if ($i>5) { - $str.="\n"; - $i=0; - } - } - return $str; -} - -1; \ No newline at end of file +################################################################ +# $Id$ +# Maintainer: Adimarantis +# 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 +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# The GNU General Public License can be found at +# http://www.gnu.org/copyleft/gpl.html. +# 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. +# +# This script is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +################################################################ + +package FHEM::Text::Unicode; +use strict; +use warnings; +use Exporter 'import'; +our @EXPORT_OK = qw (formatTextUnicode formatStringUnicode demoUnicode demoUnicodeHTML); +our %EXPORT_TAGS = (ALL => [@EXPORT_OK]); + +#define globally for demo +#Emoticons +my @mrep = ( + [":\\)","\x{1F600}"], + [":-\\)","\x{1F600}"], + [":\\(","\x{1F641}"], + ["<3","\x{2665}"], + [";-\\)","\x{1F609}"], + [":\\+1:","\x{1F44D}"], + [":smile:","\x{1F600}"], + [":sad:","\x{1F641}"], + [":heart:","\x{2665}"], + [":wink:","\x{1F609}"], + [":thumbsup:","\x{1F44D}"], + ); +#html like styles +my @htags = ( + ["bold" ,"",""], + ["italic","",""], + ["bold-italic","",""], + ["mono","",""], + ["mono","",""], + ["underline","",""], + ["strikethrough","",""], + ["fraktur","",""], + ["script",""], + ["square","",""], +); +#Single replacements in html mode +my @hrep = ( + ["
    ","\n"], +); +#Markdown styles +my @mtags = ( + ["italic","__","__"], + ["strikethrough","~~","~~"], + ["bold","\\*\\*","\\*\\*"], + ["mono","``","``"], +); + +#Convert text with Markdown/html to Unicode +#Arguments: +#$format: +# html: Only apply HTML-like formatting like .... +# markdown: Only apply Markdown formatting like __text__ and emoticon replacements +# both: Apply both formatting styles +#$msg: ASCII String that should be replaced +#returns: Unicode string with applied replacements +#To display all replacements use the demoUnicode() or demoUnicodeHTML() function +sub formatTextUnicode($$) { + my ($format,$msg) = @_; + my @tags; + my @reps; + + if ($format eq "markdown" || $format eq "both") { + push @tags, @mtags; + push @reps, @mrep; + } + if ($format eq "html" || $format eq "both") { + push @tags, @htags; + push @reps, @hrep; + } + + #First pass, replace singe special characters + foreach my $arr (@reps) { + my @val=@$arr; + $msg =~ s/$val[0]/$val[1]/sg; + } + + my $found=1; + my $matches=0; + my $text; + while ($found && $matches<100) { + $matches++; + $found=0; + foreach my $arr (@tags) { + my @val=@$arr; + $msg =~ /$val[1](.*?)$val[2]/s; + if (defined $1) { + $text=formatStringUnicode($val[0],$1); + if (defined $text) { + $msg =~ s/$val[1].*?$val[2]/$text/s; + $found=1; + } + } + } + } + return $msg; +} + +#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 +#$str: ASCII String that should be converted +#returns: Unicode String with style applied +sub formatStringUnicode($$) { + my ($font,$str) = @_; + + if ($font eq "underline") { + $str =~ s/./$&\x{332}/g; + return $str; + } + if ($font eq "strikethrough") { + $str =~ s/./$&\x{336}/g; + return $str; + } + + my %uc = ( + "bold" => [0x1d41a,0x1d400,0x1d7ce], + "italic" => [0x1d44e,0x1d434,0x30], + "bold-italic" => [0x1d482,0x1d468,0x30], + "script" => [0x1d4ea,0x1d4d0,0x30], #Using boldface since normal misses some letters + "fraktur" => [0x1d586,0x1d56c,0x30],#Using boldface since normal misses some letters + "square" => [0x1f130,0x1f130,0x30], + "mono" => [0x1d68a,0x1d670,0x30], + ); + + 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); + $_=$str; + #"no warnings" to prevent a bug in older Perl versions (seen in 5.28) that warns about + #"Replacement list is longer than search list" when using ASCII->Unicode replacements + eval "{no warnings; tr/a-zA-Z0-9/$rep/}"; + return undef if $@; +#Special handling for characters missing in some fonts +# 0x1d455 => 0x1d629, #italic h -> italic sans-serif h or 0x210e (planck constant) +# 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(); + $str =~ s//sg; + return $str; +} + +# Returns a printable String that showcases all possible replacements and their syntax +sub demoUnicode { + my $str; + $str.="HTML style formatting:\n"; + foreach my $arr (@htags) { + my @val=@$arr; + $str .= formatStringUnicode($val[0],$val[0]." TEXT 123").": $val[1]text$val[2]\n"; + } + $str.="newline:
    \n"; + + $str.="\nMarkdown style formatting:\n"; + foreach my $arr (@mtags) { + my @val=@$arr; + my $md= formatStringUnicode($val[0],$val[0]." TEXT 123").": $val[1]text$val[2]\n"; + $md =~ s/\\//g; + $str.=$md; + } + my $i=0; + foreach my $arr (@mrep) { + my @val=@$arr; + my $emo=$val[0]; + $emo =~ s/\\//g; + $str.="$val[1]=$emo "; + $i++; + if ($i>5) { + $str.="\n"; + $i=0; + } + } + return $str; +} + +1;