diff --git a/fhem/CHANGED b/fhem/CHANGED index 4bb8240c4..8ae9e2500 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_TelegramBot reply set command / allowedCommands as restriction - change: 49_SSCam: get "snapfileinfo" will get back an Infomessage if Reading "LastSnapId" isn't available - feature: dummy attribute useSetExtensions diff --git a/fhem/FHEM/50_TelegramBot.pm b/fhem/FHEM/50_TelegramBot.pm index 6b29d4e1c..0e4892eb2 100644 --- a/fhem/FHEM/50_TelegramBot.pm +++ b/fhem/FHEM/50_TelegramBot.pm @@ -125,11 +125,19 @@ # 1.6 2016-04-08 text customization for replies/messages and favorite descriptions # Fix: contact handling failed (/ in contact names ??) +# Reply keyboards also for sendVoice/sendDocument ect +# reply msg id in sendit - new set cmd reply +# Fix: reset also removes retry timer +# TEMP: SNAME in hash is needed for allowed (SNAME reflects if the TCPServer device name) +# Remove unnecessary attribute setters +# added allowedCommands and doc (with modification of allowed_... device) +# allowedCommands only modified on the allowed_... device +# 1.7 2016-05-05 reply set command / allowedCommands as restriction # # ############################################################################## # TASKS -# +# # Look for solution on space at beginning of line --> checked that data is sent correctly to telegram but does not end up in the message # # allow keyboards in the device api @@ -138,7 +146,6 @@ # ############################################################################## # Ideas / Future -# add replyTo # ############################################################################## @@ -164,7 +171,7 @@ sub TelegramBot_Set($@); sub TelegramBot_Get($@); sub TelegramBot_Callback($$$); -sub TelegramBot_SendIt($$$$$;$); +sub TelegramBot_SendIt($$$$$;$$); sub TelegramBot_checkAllowedPeer($$$); sub TelegramBot_SplitFavoriteDef($$); @@ -189,6 +196,8 @@ my %sets = ( "replaceContacts" => "textField", "reset" => undef, + "reply" => "textField", + "zDebug" => "textField" ); @@ -250,7 +259,7 @@ sub TelegramBot_Initialize($) { $hash->{SetFn} = "TelegramBot_Set"; $hash->{AttrFn} = "TelegramBot_Attr"; $hash->{AttrList} = "defaultPeer defaultPeerCopy:0,1 pollingTimeout cmdKeyword cmdSentCommands favorites:textField-long cmdFavorites cmdRestrictedPeer ". "cmdTriggerOnly:0,1 saveStateOnContactChange:1,0 maxFileSize maxReturnSize cmdReturnEmptyResult:1,0 pollingVerbose:1_Digest,2_Log,0_None ". - "allowUnknownContacts:1,0 textResponseConfirm:textField textResponseCommands:textField ". + "allowUnknownContacts:1,0 textResponseConfirm:textField textResponseCommands:textField allowedCommands ". "textResponseFavorites:textField textResponseResult:textField textResponseUnauthorized:textField ". " maxRetries:0,1,2,3,4,5 ".$readingFnAttributes; } @@ -385,8 +394,16 @@ sub TelegramBot_Set($@) my $ret = undef; - if( ($cmd eq 'message') || ($cmd eq 'msg') || ($cmd =~ /^send.*/ ) ) { + if( ($cmd eq 'message') || ($cmd eq 'msg') || ($cmd eq 'reply') || ($cmd =~ /^send.*/ ) ) { + my $msgid; + + if ($cmd eq 'reply') { + return "TelegramBot_Set: Command $cmd, no peer, msgid and no text/file specified" if ( $numberOfArgs < 3 ); + $msgid = shift @args; + $numberOfArgs--; + } + return "TelegramBot_Set: Command $cmd, no peers and no text/file specified" if ( $numberOfArgs < 2 ); my $sendType = 0; @@ -394,7 +411,9 @@ sub TelegramBot_Set($@) my $peers; while ( $args[0] =~ /^@(..+)$/ ) { my $ppart = $1; + return "TelegramBot_Set: Command $cmd, need exactly one peer" if ( ($cmd eq 'reply') && ( defined( $peers ) ) ); $peers .= " " if ( defined( $peers ) ); + $peers = "" if ( ! defined( $peers ) ); $peers .= $ppart; shift @args; @@ -435,7 +454,7 @@ sub TelegramBot_Set($@) } Log3 $name, 5, "TelegramBot_Set $name: start send for cmd :$cmd: and sendType :$sendType:"; - $ret = TelegramBot_SendIt( $hash, $peers, $msg, $addPar, $sendType ); + $ret = TelegramBot_SendIt( $hash, $peers, $msg, $addPar, $sendType, $msgid ); } elsif($cmd eq 'zDebug') { # for internal testing only @@ -564,19 +583,7 @@ sub TelegramBot_Attr(@) { # $name is device name # aName and aVal are Attribute name and value if ($cmd eq "set") { - if ($aName eq 'defaultPeer') { - $attr{$name}{'defaultPeer'} = $aVal; - - } elsif ($aName eq 'cmdKeyword') { - $attr{$name}{'cmdKeyword'} = $aVal; - - } elsif ($aName eq 'cmdSentCommands') { - $attr{$name}{'cmdSentCommands'} = $aVal; - - } elsif ($aName eq 'cmdFavorites') { - $attr{$name}{'cmdFavorites'} = $aVal; - - } elsif ($aName eq 'favorites') { + if ($aName eq 'favorites') { $attr{$name}{'favorites'} = $aVal; # Empty current alias list in hash @@ -604,7 +611,6 @@ sub TelegramBot_Attr(@) { } elsif ($aName eq 'cmdRestrictedPeer') { $aVal =~ s/^\s+|\s+$//g; - $attr{$name}{'cmdRestrictedPeer'} = $aVal; } elsif ( ($aName eq 'defaultPeerCopy') || ($aName eq 'saveStateOnContactChange') || @@ -613,25 +619,13 @@ sub TelegramBot_Attr(@) { ($aName eq 'allowUnknownContacts') ) { $aVal = ($aVal eq "1")? "1": "0"; - } elsif ($aName eq 'maxFileSize') { - if ( $aVal !~ /^[[:digit:]]+$/ ) { - return "\"TelegramBot_Attr: \" maxFileSize needs to be given in digits only"; - } - - } elsif ($aName eq 'maxReturnSize') { - if ( $aVal !~ /^[[:digit:]]+$/ ) { - return "\"TelegramBot_Attr: \" maxReturnSize needs to be given in digits only"; - } - - } elsif ($aName eq 'maxRetries') { - if ( $aVal !~ /^[[:digit:]]$/ ) { - return "\"TelegramBot_Attr: \" maxRetries needs to be given in digits only"; - } + } elsif ( ($aName eq 'maxFileSize') || + ($aName eq 'maxReturnSize') || + ($aName eq 'maxRetries') ) { + return "\"TelegramBot_Attr: \" $aName needs to be given in digits only" if ( $aVal !~ /^[[:digit:]]+$/ ); } elsif ($aName eq 'pollingTimeout') { - if ( $aVal !~ /^[[:digit:]]+$/ ) { - return "\"TelegramBot_Attr: \" pollingTimeout needs to be given in digits only"; - } + return "\"TelegramBot_Attr: \" $aName needs to be given in digits only" if ( $aVal !~ /^[[:digit:]]+$/ ); # let all existing methods run into block RemoveInternalTimer($hash); $hash->{POLLING} = -1; @@ -641,7 +635,17 @@ sub TelegramBot_Attr(@) { } elsif ($aName eq 'pollingVerbose') { return "\"TelegramBot_Attr: \" Incorrect value given for pollingVerbose" if ( $aVal !~ /^((1_Digest)|(2_Log)|(0_None))$/ ); - $attr{$name}{'pollingVerbose'} = $aVal; + + } elsif ($aName eq 'allowedCommands') { + my $allowedName = "allowed_$name"; + my $exists = ($defs{$allowedName} ? 1 : 0); + AnalyzeCommand(undef, "defmod $allowedName allowed"); + AnalyzeCommand(undef, "attr $allowedName validFor $name"); + AnalyzeCommand(undef, "attr $allowedName $aName ".$aVal); + Log3 $name, 3, "TelegramBot_Attr $name: ".($exists ? "modified":"created")." $allowedName with commands :$aVal:"; + # allowedCommands only set on the corresponding allowed_device + return "\"TelegramBot_Attr: \" $aName ".($exists ? "modified":"created")." $allowedName with commands :$aVal:" + } $_[3] = $aVal; @@ -818,22 +822,6 @@ sub TelegramBot_SentFavorites($$$$) { $ret = TelegramBot_SendIt( $hash, $mpeernorm, $ret, $jsonkb, 0 ); - -############ OLD Favorites sent as message -# Log3 $name, 3, "TelegramBot_SentFavorites Favorites :".scalar(@clist).": "; - # my $cnt = 0; - # $slc = ""; - # my $ck = AttrVal($name,'cmdKeyword',""); - - # foreach my $cs ( @clist ) { - # $cnt += 1; - # $slc .= $cnt."\n $ck ".$cs."\n"; - # } - - # my $defpeer = AttrVal($name,'defaultPeer',undef); - # $defpeer = TelegramBot_GetIdForPeer( $hash, $defpeer ) if ( defined( $defpeer ) ); - # $ret = "TelegramBot fhem : ($mpeernorm)\n Favorites \n\n".$slc; - # $ret = TelegramBot_SendIt( $hash, $defpeer, $ret, $mid, 0 ); } return $ret; @@ -938,7 +926,7 @@ sub TelegramBot_ExecuteCommand($$$) { my $isMediaStream = 0; if ( ! defined( $ret ) ) { - $ret = AnalyzeCommand( undef, $cmd, "" ); + $ret = AnalyzeCommand( $hash, $cmd ); # Check for image/doc/audio stream in return (-1 image ( $isMediaStream ) = TelegramBot_IdentifyStream( $hash, $ret ) if ( defined( $ret ) ); @@ -1172,11 +1160,11 @@ sub TelegramBot_DoUrlCommand($$) ##################################### # INTERNAL: Function to send a photo (and text message) to a peer and handle result # addPar is caption for images / keyboard for text -sub TelegramBot_SendIt($$$$$;$) +sub TelegramBot_SendIt($$$$$;$$) { my ( $hash, @args) = @_; - my ( $peers, $msg, $addPar, $isMedia, $retryCount) = @args; + my ( $peers, $msg, $addPar, $isMedia, $replyid, $retryCount) = @args; my $name = $hash->{NAME}; if ( ! defined( $retryCount ) ) { @@ -1184,7 +1172,7 @@ sub TelegramBot_SendIt($$$$$;$) } # increase retrycount for next try - $args[4] = $retryCount+1; + $args[5] = $retryCount+1; Log3 $name, 5, "TelegramBot_SendIt $name: called "; @@ -1260,10 +1248,6 @@ sub TelegramBot_SendIt($$$$$;$) # add msg (no file) $ret = TelegramBot_AddMultipart($hash, \%TelegramBot_hu_do_params, "text", undef, $msg, 0 ) if ( ! defined( $ret ) ); - if ( defined( $addPar ) ) { - $ret = TelegramBot_AddMultipart($hash, \%TelegramBot_hu_do_params, "reply_markup", undef, $addPar, 0 ) if ( ! defined( $ret ) ); - } - } elsif ( abs($isMedia) == 1 ) { # Photo send $hash->{sentMsgText} = "Image: ".TelegramBot_MsgForLog($msg, ($isMedia<0) ). @@ -1302,6 +1286,14 @@ sub TelegramBot_SendIt($$$$$;$) $ret = TelegramBot_AddMultipart($hash, \%TelegramBot_hu_do_params, "document", undef, $msg, $isMedia ) if ( ! defined( $ret ) ); } + if ( defined( $replyid ) ) { + $ret = TelegramBot_AddMultipart($hash, \%TelegramBot_hu_do_params, "reply_to_message_id", undef, $replyid, 0 ) if ( ! defined( $ret ) ); + } + + if ( defined( $addPar ) ) { + $ret = TelegramBot_AddMultipart($hash, \%TelegramBot_hu_do_params, "reply_markup", undef, $addPar, 0 ) if ( ! defined( $ret ) ); + } + # finalize multipart $ret = TelegramBot_AddMultipart($hash, \%TelegramBot_hu_do_params, undef, undef, undef, 0 ) if ( ! defined( $ret ) ); @@ -1491,11 +1483,9 @@ sub TelegramBot_RetrySend($) my $name = $hash->{NAME}; - my $args = $param->{args}; - my $ref = $param->{args}; - Log3 $name, 4, "TelegramBot_Retrysend $name: retry @$ref[4] :@$ref[0]: -:@$ref[1]: "; - TelegramBot_SendIt( $hash, @$ref[0], @$ref[1], @$ref[2], @$ref[3], @$ref[4] ); + Log3 $name, 4, "TelegramBot_Retrysend $name: reply @$ref[4] retry @$ref[5] :@$ref[0]: -:@$ref[1]: "; + TelegramBot_SendIt( $hash, @$ref[0], @$ref[1], @$ref[2], @$ref[3], @$ref[4], @$ref[5] ); } @@ -1649,14 +1639,14 @@ sub TelegramBot_Callback($$$) # handle retry # ret defined / args defined in params if ( ( $ret ne "SUCCESS" ) && ( defined( $param->{args} ) ) ) { - my $wait = $param->{args}[4]; + my $wait = $param->{args}[5]; my $maxRetries = AttrVal($name,'maxRetries',0); if ( $wait <= $maxRetries ) { # calculate wait time 10s / 100s / 1000s ~ 17min / 10000s ~ 3h / 100000s ~ 30h $wait = 10**$wait; - Log3 $name, 4, "TelegramBot_Callback $name: do retry ".$param->{args}[4]." timer: $wait (ret: $ret) for msg ". + Log3 $name, 4, "TelegramBot_Callback $name: do retry ".$param->{args}[5]." timer: $wait (ret: $ret) for msg ". $param->{args}[0]." : ".$param->{args}[1]; # set timer @@ -1682,7 +1672,7 @@ sub TelegramBot_Callback($$$) if ( scalar( @{ $hash->{sentQueue} } ) ) { my $ref = shift @{ $hash->{sentQueue} }; Log3 $name, 5, "TelegramBot_Callback $name: handle queued send with :@$ref[0]: -:@$ref[1]: "; - TelegramBot_SendIt( $hash, @$ref[0], @$ref[1], @$ref[2], @$ref[3], @$ref[4] ); + TelegramBot_SendIt( $hash, @$ref[0], @$ref[1], @$ref[2], @$ref[3], @$ref[4], @$ref[5] ); } } @@ -1930,10 +1920,16 @@ sub TelegramBot_Setup($) { $hash->{STATE} = "Undefined"; $hash->{POLLING} = -1; + + # Temp?? SNAME is required for allowed (normally set in TCPServerUtils) + $hash->{SNAME} = $name; # Ensure queueing is not happening delete( $hash->{sentQueue} ); delete( $hash->{sentMsgResult} ); + + # remove timer for retry + RemoveInternalTimer(\%TelegramBot_hu_do_params); $hash->{URL} = "https://api.telegram.org/bot".$hash->{Token}."/"; @@ -2305,7 +2301,7 @@ sub TelegramBot_checkAllowedPeer($$$) { # send unauthorized to defaultpeer my $defpeer = AttrVal($name,'defaultPeer',undef); if ( defined( $defpeer ) ) { - AnalyzeCommand( undef, "set $name message $ret", "" ); + AnalyzeCommand( undef, "set $name message $ret" ); } return 0; @@ -2490,7 +2486,7 @@ sub TelegramBot_BinaryFileWrite($$$) { define <name> TelegramBot <token>

Defines a TelegramBot device using the specified token perceived from botfather -

+
Example: