<commit_before>package Mojo::Webqq::Plugin::Openqq;
our $PRIORITY = 98;
use strict;
use POSIX qw();
use Mojo::Util qw();
use List::Util qw(first);
use Mojo::Webqq::Server;
use Mojo::Webqq::List;
my  $server;
my  $check_event_list;
sub call{
    my $client = shift;
    my $data   =  shift;
    $check_event_list = Mojo::Webqq::List->new(max_size=>$data->{check_event_list_max_size} || 20);
    $data->{post_media_data} = 1 if not defined $data->{post_media_data};
    $data->{post_event} = 1 if not defined $data->{post_event};
    $data->{post_event_list} = [qw(login stop state_change input_qrcode new_group new_friend new_group_member lose_group lose_friend lose_group_member)]
        if ref $data->{post_event_list} ne 'ARRAY';

    if(defined $data->{poll_api}){
        $client->on('_mojo_webqq_plugin_openqq_poll_over' => sub{
            $client->http_get($data->{poll_api},sub{
                $client->timer($data->{poll_interval} || 5,sub {$client->emit('_mojo_webqq_plugin_openqq_poll_over');});
            });
        });
        $client->emit('_mojo_webqq_plugin_openqq_poll_over');
    }

    $client->on(all_event => sub{
        my($client,$event,@args) =@_;
        return if not first {$event eq $_} @{ $data->{post_event_list} };
        if(defined $data->{post_api} and ($event eq  'login' or $event eq 'stop' or $event eq 'state_change') ){
            my $post_json = {};
            $post_json->{post_type} = "event";
            $post_json->{event} = $event;
            $post_json->{params} = [@args];
            my($data,$ua,$tx) = $client->http_post($data->{post_api},{ua_connect_timeout=>5,ua_request_timeout=>5,ua_inactivity_timeout=>5,ua_retry_times=>2},json=>$post_json);
            if($tx->success){
                $client->debug("插件[".__PACKAGE__ ."]事件[".$event . "](@args)上报成功");
            }
            else{
                $client->warn("插件[".__PACKAGE__ . "]事件[".$event."](@args)上报失败:" . $client->encode("utf8",$tx->error->{message}));
            } 
        }
        elsif(defined $data->{post_api} and $event eq 'input_qrcode'){
            my ($qrcode_path,$qrcode_data) = @args;
            eval{ $qrcode_data = Mojo::Util::b64_encode($qrcode_data);};
            if($@){
                $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败: $@");
                return;
            }
            my $post_json = {};
            $post_json->{post_type} = "event";
            $post_json->{event} = $event;
            $post_json->{params} = [$qrcode_path,$qrcode_data];
            my($data,$ua,$tx) = $client->http_post($data->{post_api},json=>$post_json);
            if($tx->success){
                $client->debug("插件[".__PACKAGE__ ."]事件[".$event . "]上报成功");
            }
            else{
                $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败:" . $client->encode("utf8",$tx->error->{message}));
            }
        }
        elsif($event =~ /^new_group|lose_group|new_friend|lose_friend|new_discuss|lose_discuss|new_group_member|lose_group_member|new_discuss_member|lose_discuss_member$/){
            my $post_json = {};
            $post_json->{post_type} = "event";
            $post_json->{event} = $event;
            if($event =~ /^new_group_member|lose_group_member$/){
                $post_json->{params} = [$args[0]->to_json_hash(0),$args[1]->to_json_hash(0)];
            }
            else{
                $post_json->{params} = [$args[0]->to_json_hash(0)];
            }
            $check_event_list->append($post_json);
            $client->http_post($data->{post_api},json=>$post_json,sub{
                my($data,$ua,$tx) = @_;
                if($tx->success){
                    $client->debug("插件[".__PACKAGE__ ."]事件[".$event."]上报成功");
                }
                else{
                    $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败: ".$client->encode("utf8",$tx->error->{message}));
                }
            }) if defined $data->{post_api};
        }
        elsif($event =~ /^group_property_change|group_member_property_change|friend_property_change|user_property_change$/){
            my ($object,$property,$old,$new) = @args;
            my $post_json = {
                post_type => "event",
                event     => $event,
                params    => [$object->to_json_hash(0),$property,$old,$new],
            };
            $check_event_list->append($post_json);
            $client->http_post($data->{post_api},json=>$post_json,sub{
                my($data,$ua,$tx) = @_;
                if($tx->success){
                    $client->debug("插件[".__PACKAGE__ ."]事件[".$event."]上报成功");
                }
                else{
                    $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败: ".$client->encode("utf8",$tx->error->{message}));
                }
            }) if defined $data->{post_api};

        }
        elsif($event =~ /^update_user|update_friend|update_group$/){
            my ($ref) = @args;
            my $post_json = {
                post_type => "event",
                event     => $event,
                params    => [$event eq 'update_user'?$ref->to_json_hash():map {$_->to_json_hash()} @{$ref}], 
            };
            $client->http_post($data->{post_api},json=>$post_json,sub{
                my($data,$ua,$tx) = @_;
                if($tx->success){
                    $client->debug("插件[".__PACKAGE__ ."]事件[".$event."]上报成功");
                }
                else{
                    $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败: ".$client->encode("utf8",tx->error->{message}));
                }
            }) if defined $data->{post_api};
        }
    }) if $data->{post_event};

    $client->on(receive_message=>sub{
        my($client,$msg) = @_;
        return if $msg->type !~ /^friend_message|group_message|discuss_message|sess_message$/;
        my $post_json = $msg->to_json_hash;
        #delete $post_json->{media_data} if ($post_json->{format} eq "media" and ! $data->{post_media_data});
        $post_json->{post_type} = "receive_message";
        $check_event_list->append($post_json);
        $client->http_post($data->{post_api},json=>$post_json,sub{
            my($data,$ua,$tx) = @_;
            if($tx->success){
                $client->debug("插件[".__PACKAGE__ ."]接收消息[".$msg->id."]上报成功");
                if($tx->res->headers->content_type =~m#text/json|application/json#){
                    #文本类的返回结果必须是json字符串
                    my $json;
                    eval{$json = $client->from_json($tx->res->body)};
                    if($@){$client->warn($@);return}
                    if(defined $json){
                        #暂时先不启用format的属性
                        #{code=>0,reply=>"回复的消息",format=>"text"}
                        #if((!defined $json->{format}) or (defined $json->{format} and $json->{format} eq "text")){
                        #    $msg->reply(Encode::encode("utf8",$json->{reply})) if defined $json->{reply};
                        #}

                        $msg->reply($json->{reply}) if defined $json->{reply};
                        if($msg->type eq "group_message" and defined $json->{shutup} and $json->{shutup} == 1){
                            $msg->sender->shutup($json->{shutup_time} || 60);
                        }
                        #$msg->reply_media($json->{media}) if defined $json->{media} and $json->{media} =~ /^https?:\/\//;

                    }
                }
                #elsif($tx->res->headers->content_type =~ m#image/#){
                #   #发送图片，暂未实现
                #}
            }
            else{
                $client->warn("插件[".__PACKAGE__ . "]接收消息[".$msg->id."]上报失败: ". $client->encode("utf8",$tx->error->{message})); 
            }
        }) if defined $data->{post_api};
    });

    $client->on(send_message=>sub{
        my($client,$msg) = @_;
        return if $msg->type !~ /^friend_message|group_message|discuss_message|sess_message$/;
        my $post_json = $msg->to_json_hash;
        #delete $post_json->{media_data} if ($post_json->{format} eq "media" and ! $data->{post_media_data});
        $post_json->{post_type} = "send_message";
        $check_event_list->append($post_json);
        $client->http_post($data->{post_api},json=>$post_json,sub{
            my($data,$ua,$tx) = @_;
            if($tx->success){
                $client->debug("插件[".__PACKAGE__ ."]发送消息[".$msg->id."]上报成功");
                if($tx->res->headers->content_type =~m#text/json|application/json#){
                    #文本类的返回结果必须是json字符串
                    my $json;
                    eval{$json = $tx->res->json};
                    if($@){$client->warn($@);return}
                    if(defined $json){
                        #{code=>0,reply=>"回复的消息",format=>"text"}
                        if((!defined $json->{format}) or (defined $json->{format} and $json->{format} eq "text")){
                            $msg->reply($json->{reply}) if defined $json->{reply};
                        }
                    }
                }
                #elsif($tx->res->headers->content_type =~ m#image/#){
                #   #发送图片，暂未实现
                #}
            }
            else{
                $client->warn("插件[".__PACKAGE__ . "]发送消息[".$msg->id."]上报失败: ".$client->encode("utf8",$tx->error->{message})); 
            }
        }) if defined $data->{post_api};
    });
    package Mojo::Webqq::Plugin::Openqq::App::Controller;
    use Mojo::JSON ();
    use Mojo::Util ();
    use base qw(Mojolicious::Controller);
    sub render{
        my $self = shift;
        if($_[0] eq 'json'){
            $self->res->headers->content_type('application/json');
            $self->SUPER::render(data=>Mojo::JSON::to_json($_[1]),@_[2..$#_]);
        }
        else{$self->SUPER::render(@_)}
    }
    sub safe_render{
        my $self = shift;<commit_msg>修复Openqq插件上报接口返回reply回复内容时产生大量报错的问题 感谢 @Hubertzhang<commit_after>package Mojo::Webqq::Plugin::Openqq;
our $PRIORITY = 98;
use strict;
use POSIX qw();
use Mojo::Util qw();
use List::Util qw(first);
use Mojo::Webqq::Server;
use Mojo::Webqq::List;
my  $server;
my  $check_event_list;
sub call{
    my $client = shift;
    my $data   =  shift;
    $check_event_list = Mojo::Webqq::List->new(max_size=>$data->{check_event_list_max_size} || 20);
    $data->{post_media_data} = 1 if not defined $data->{post_media_data};
    $data->{post_event} = 1 if not defined $data->{post_event};
    $data->{post_event_list} = [qw(login stop state_change input_qrcode new_group new_friend new_group_member lose_group lose_friend lose_group_member)]
        if ref $data->{post_event_list} ne 'ARRAY';

    if(defined $data->{poll_api}){
        $client->on('_mojo_webqq_plugin_openqq_poll_over' => sub{
            $client->http_get($data->{poll_api},sub{
                $client->timer($data->{poll_interval} || 5,sub {$client->emit('_mojo_webqq_plugin_openqq_poll_over');});
            });
        });
        $client->emit('_mojo_webqq_plugin_openqq_poll_over');
    }

    $client->on(all_event => sub{
        my($client,$event,@args) =@_;
        return if not first {$event eq $_} @{ $data->{post_event_list} };
        if(defined $data->{post_api} and ($event eq  'login' or $event eq 'stop' or $event eq 'state_change') ){
            my $post_json = {};
            $post_json->{post_type} = "event";
            $post_json->{event} = $event;
            $post_json->{params} = [@args];
            my($data,$ua,$tx) = $client->http_post($data->{post_api},{ua_connect_timeout=>5,ua_request_timeout=>5,ua_inactivity_timeout=>5,ua_retry_times=>2},json=>$post_json);
            if($tx->success){
                $client->debug("插件[".__PACKAGE__ ."]事件[".$event . "](@args)上报成功");
            }
            else{
                $client->warn("插件[".__PACKAGE__ . "]事件[".$event."](@args)上报失败:" . $client->encode("utf8",$tx->error->{message}));
            } 
        }
        elsif(defined $data->{post_api} and $event eq 'input_qrcode'){
            my ($qrcode_path,$qrcode_data) = @args;
            eval{ $qrcode_data = Mojo::Util::b64_encode($qrcode_data);};
            if($@){
                $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败: $@");
                return;
            }
            my $post_json = {};
            $post_json->{post_type} = "event";
            $post_json->{event} = $event;
            $post_json->{params} = [$qrcode_path,$qrcode_data];
            my($data,$ua,$tx) = $client->http_post($data->{post_api},json=>$post_json);
            if($tx->success){
                $client->debug("插件[".__PACKAGE__ ."]事件[".$event . "]上报成功");
            }
            else{
                $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败:" . $client->encode("utf8",$tx->error->{message}));
            }
        }
        elsif($event =~ /^new_group|lose_group|new_friend|lose_friend|new_discuss|lose_discuss|new_group_member|lose_group_member|new_discuss_member|lose_discuss_member$/){
            my $post_json = {};
            $post_json->{post_type} = "event";
            $post_json->{event} = $event;
            if($event =~ /^new_group_member|lose_group_member$/){
                $post_json->{params} = [$args[0]->to_json_hash(0),$args[1]->to_json_hash(0)];
            }
            else{
                $post_json->{params} = [$args[0]->to_json_hash(0)];
            }
            $check_event_list->append($post_json);
            $client->http_post($data->{post_api},json=>$post_json,sub{
                my($data,$ua,$tx) = @_;
                if($tx->success){
                    $client->debug("插件[".__PACKAGE__ ."]事件[".$event."]上报成功");
                }
                else{
                    $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败: ".$client->encode("utf8",$tx->error->{message}));
                }
            }) if defined $data->{post_api};
        }
        elsif($event =~ /^group_property_change|group_member_property_change|friend_property_change|user_property_change$/){
            my ($object,$property,$old,$new) = @args;
            my $post_json = {
                post_type => "event",
                event     => $event,
                params    => [$object->to_json_hash(0),$property,$old,$new],
            };
            $check_event_list->append($post_json);
            $client->http_post($data->{post_api},json=>$post_json,sub{
                my($data,$ua,$tx) = @_;
                if($tx->success){
                    $client->debug("插件[".__PACKAGE__ ."]事件[".$event."]上报成功");
                }
                else{
                    $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败: ".$client->encode("utf8",$tx->error->{message}));
                }
            }) if defined $data->{post_api};

        }
        elsif($event =~ /^update_user|update_friend|update_group$/){
            my ($ref) = @args;
            my $post_json = {
                post_type => "event",
                event     => $event,
                params    => [$event eq 'update_user'?$ref->to_json_hash():map {$_->to_json_hash()} @{$ref}], 
            };
            $client->http_post($data->{post_api},json=>$post_json,sub{
                my($data,$ua,$tx) = @_;
                if($tx->success){
                    $client->debug("插件[".__PACKAGE__ ."]事件[".$event."]上报成功");
                }
                else{
                    $client->warn("插件[".__PACKAGE__ . "]事件[".$event."]上报失败: ".$client->encode("utf8",tx->error->{message}));
                }
            }) if defined $data->{post_api};
        }
    }) if $data->{post_event};

    $client->on(receive_message=>sub{
        my($client,$msg) = @_;
        return if $msg->type !~ /^friend_message|group_message|discuss_message|sess_message$/;
        my $post_json = $msg->to_json_hash;
        #delete $post_json->{media_data} if ($post_json->{format} eq "media" and ! $data->{post_media_data});
        $post_json->{post_type} = "receive_message";
        $check_event_list->append($post_json);
        $client->http_post($data->{post_api},json=>$post_json,sub{
            my($data,$ua,$tx) = @_;
            if($tx->success){
                $client->debug("插件[".__PACKAGE__ ."]接收消息[".$msg->id."]上报成功");
                if($tx->res->headers->content_type =~m#text/json|application/json#){
                    #文本类的返回结果必须是json字符串
                    my $json;
                    eval{$json = $client->from_json($tx->res->body)};
                    if($@){$client->warn($@);return}
                    if(defined $json){
                        #暂时先不启用format的属性
                        #{code=>0,reply=>"回复的消息",format=>"text"}
                        #if((!defined $json->{format}) or (defined $json->{format} and $json->{format} eq "text")){
                        #    $msg->reply(Encode::encode("utf8",$json->{reply})) if defined $json->{reply};
                        #}

                        $msg->reply($json->{reply}) if defined $json->{reply};
                        if($msg->type eq "group_message" and defined $json->{shutup} and $json->{shutup} == 1){
                            $msg->sender->shutup($json->{shutup_time} || 60);
                        }
                        #$msg->reply_media($json->{media}) if defined $json->{media} and $json->{media} =~ /^https?:\/\//;

                    }
                }
                #elsif($tx->res->headers->content_type =~ m#image/#){
                #   #发送图片，暂未实现
                #}
            }
            else{
                $client->warn("插件[".__PACKAGE__ . "]接收消息[".$msg->id."]上报失败: ". $client->encode("utf8",$tx->error->{message})); 
            }
        }) if defined $data->{post_api};
    });

    $client->on(send_message=>sub{
        my($client,$msg) = @_;
        return if $msg->type !~ /^friend_message|group_message|discuss_message|sess_message$/;
        my $post_json = $msg->to_json_hash;
        #delete $post_json->{media_data} if ($post_json->{format} eq "media" and ! $data->{post_media_data});
        $post_json->{post_type} = "send_message";
        $check_event_list->append($post_json);
        $client->http_post($data->{post_api},json=>$post_json,sub{
            my($data,$ua,$tx) = @_;
            if($tx->success){
                $client->debug("插件[".__PACKAGE__ ."]发送消息[".$msg->id."]上报成功");
                if($tx->res->headers->content_type =~m#text/json|application/json#){
                    #文本类的返回结果必须是json字符串
                    my $json;
                    eval{$json = $client->from_json($tx->res->body)};
                    if($@){$client->warn($@);return}
                    if(defined $json){
                        #{code=>0,reply=>"回复的消息",format=>"text"}
                        if((!defined $json->{format}) or (defined $json->{format} and $json->{format} eq "text")){
                            $msg->reply($json->{reply}) if defined $json->{reply};
                        }
                    }
                }
                #elsif($tx->res->headers->content_type =~ m#image/#){
                #   #发送图片，暂未实现
                #}
            }
            else{
                $client->warn("插件[".__PACKAGE__ . "]发送消息[".$msg->id."]上报失败: ".$client->encode("utf8",$tx->error->{message})); 
            }
        }) if defined $data->{post_api};
    });
    package Mojo::Webqq::Plugin::Openqq::App::Controller;
    use Mojo::JSON ();
    use Mojo::Util ();
    use base qw(Mojolicious::Controller);
    sub render{
        my $self = shift;
        if($_[0] eq 'json'){
            $self->res->headers->content_type('application/json');
            $self->SUPER::render(data=>Mojo::JSON::to_json($_[1]),@_[2..$#_]);
        }
        else{$self->SUPER::render(@_)}
    }
    sub safe_render{
        my $self = shift;
{'fraction_non_alphanumeric': 0.19284414796846575, 'fraction_numerical': 0.0036385688295936932, 'mean_word_length': 1.978476821192053, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 402, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6695662', 'n_tokens_mistral': 6724, 'n_tokens_neox': 6726, 'n_words': 799}