Quellcode durchsuchen

Add Discord driver

Andy Baugh vor 7 Jahren
Ursprung
Commit
a450e93559

+ 1 - 0
LICENSE-IMAGES.md

@@ -2,3 +2,4 @@ Adding this file here, as some of the imagery used in the Schema modules were no
 * XMPP: Released under the [MIT Expat License](https://commons.wikimedia.org/wiki/Category:Expat/MIT_License "MIT Expat License"). [Source](https://commons.wikimedia.org/wiki/File:XMPP_logo.svg "Wikimedia")
 * IRC: Released under the [Creative Commons Attribution-Share Alike 3.0 Unported license](https://github.com/fabianalexisinostroza/Antu/blob/master/LICENSE "CC-SA 3.0 Unported"). [Source](https://commons.wikimedia.org/wiki/File:Antu_irc.svg "Wikimedia")
 * Slack: Released under the terms of [Slack's Branding Guidelines](https://slack.com/brand-guidelines "Slack's Branding Guidelines"). [Source](https://brandfolder.com/slack "Slack Icons @ BrandFolder")
+* Discord: Released under the terms of [Discord's Branding Guidelines](https://discordapp.com/branding "Discord's Branding Guidelines"). [Source](https://discordapp.com/assets/f8389ca1a741a115313bede9ac02e2c0.svg)

+ 1 - 0
README.md

@@ -6,6 +6,7 @@ Current plugins:
 * XMPP  -- Stable XMPP provider (well, as stable as Net::XMPP is, anyways). See issue #2
 * IRC   -- New provider, needs more testing by users out in the wild. "Works for Me"
 * Slack -- Works presuming you have an incoming WebHook URL, much like CpanelRicky's MatterMost plugin.
+* Discord -- Similar to Slack, use an incoming WebHook URL.
 
 Installation and Use:
 ---------------------

+ 105 - 0
lib/Cpanel/iContact/Provider/Discord.pm

@@ -0,0 +1,105 @@
+package Cpanel::iContact::Provider::Discord;
+
+use strict;
+use warnings;
+
+use parent 'Cpanel::iContact::Provider';
+
+use Try::Tiny;
+
+=encoding utf-8
+
+=head1 NAME
+
+Cpanel::iContact::Provider::Discord - Backend for the Discord iContact module
+
+=head1 SYNOPSIS
+
+    use Cpanel::iContact::Provider::Discord;
+
+    my $notifier = Cpanel::iContact::Provider::Discord->new();
+    $notifier->send();
+
+
+=head1 DESCRIPTION
+
+Provide backend accessor for the Discord iContact module.
+
+=cut
+
+=head2 send
+
+Sends off the notification over to your hipchat room/user
+
+=over 2
+
+=item Input
+
+=over 3
+
+None
+
+=back
+
+=item Output
+
+=over 3
+
+Truthy value on success, exception on failure.
+
+=back
+
+=back
+
+=cut
+
+sub send {
+    my ($self) = @_;
+
+    my $args_hr    = $self->{'args'};
+    my $contact_hr = $self->{'contact'};
+
+    my @errs;
+
+    require Cpanel::HTTP::Client;
+    my $ua = Cpanel::HTTP::Client->new( 'default_headers' => { 'content-type' => 'application/json' } )->die_on_http_error();
+
+    my $subject = $args_hr->{'subject'};
+    my $message = ${ $args_hr->{'text_body'} };
+
+    require Cpanel::AdminBin::Serializer;
+    my $message_json = Cpanel::AdminBin::Serializer::Dump(
+        {
+            'content'     => "$subject\n\n$message",
+        }
+    );
+
+    # Send it
+    foreach my $destination ( @{ $args_hr->{'to'} } ) {
+        try {
+            my $res = $ua->request( 'POST', $destination, { 'content' => $message_json } );
+            die( sprintf "Error %d: %s", $res->status(), $res->reason() ) if !$res->success();
+        }
+        catch {
+            require Cpanel::Exception;
+            push(
+                @errs,
+                Cpanel::Exception::create(
+                    'ConnectionFailed',
+                    'The system failed to send the message to “[_1]” due to an error: [_2]',
+                    [ $destination, $_ ]
+                )
+            );
+        };
+    }
+
+    if (@errs) {
+
+        # Module should already be loaded above
+        die Cpanel::Exception::create( 'Collection', [ exceptions => \@errs ] );
+    }
+
+    return 1;
+}
+
+1;

+ 123 - 0
lib/Cpanel/iContact/Provider/Schema/Discord.pm

@@ -0,0 +1,123 @@
+package Cpanel::iContact::Provider::Schema::Discord;
+
+use strict;
+use warnings;
+
+# Name is always uc(MODULE)
+
+=encoding utf-8
+
+=head1 NAME
+
+Cpanel::iContact::Provider::Schema::Discord - Schema for the HipChat iContact module
+
+=head1 SYNOPSIS
+
+    use Cpanel::iContact::Provider::Schema::Discord;
+
+    my $settings = Cpanel::iContact::Provider::Schema::Discord::get_settings();
+
+    my $config = Cpanel::iContact::Provider::Schema::Discord::get_config();
+
+
+=head1 DESCRIPTION
+
+Provide settings and configuration for the HipChat iContact module.
+
+=cut
+
+=head2 get_settings
+
+Provide config data for TweakSettings that will be saved in
+/etc/wwwacct.conf.shadow
+
+=over 2
+
+=item Input
+
+=over 3
+
+None
+
+=back
+
+=item Output
+
+=over 3
+
+A hashref that can be injected into Whostmgr::TweakSettings::Basic's %Conf
+with the additional help and label keys that are used in the display of the
+tweak settings.
+
+=back
+
+=back
+
+=cut
+
+sub get_settings {
+    my $help = <<HALP;
+Discord Incoming Webhook URL(s): URL created for sending notifications to the destination(s) you configured for the cPanel & WHM Notifications app in Discord, separated by commas.
+<br />In order to create an incoming webhook for the channel(s)/user(s) you wish to notify, please go to 'Edit Channel > Incoming WebHooks' and add one.
+in Discord's 'App Directory' for your team.
+HALP
+    return {
+        'CONTACTDISCORD' => {
+            'name'     => 'Discord',
+            'shadow'   => 1,
+            'type'     => 'text',
+            'checkval' => sub {
+                my $value = shift();
+                $value =~ s/^\s+|\s+$//g; # Trim
+
+                return $value if $value eq q{};
+
+                my @urls = split m{\s*,\s*}, $value;
+
+                return join( ',', grep ( m{^https?://}, @urls ) );
+            },
+            'label' => 'Discord Incoming Webhook URL(s)',
+            'help'  => $help,
+        }
+    };
+}
+
+=head2 get_config
+
+Provide configuration for the module.
+
+=over 2
+
+=item Input
+
+=over 3
+
+None
+
+=back
+
+=item Output
+
+=over 3
+
+A hash ref containing the following key values:
+
+  default_level:    The iContact default contact level (All)
+  display_name:     The name displayed on the Contact Manager page in WHM.
+
+=back
+
+=back
+
+=cut
+
+sub get_config {
+    return {
+        'default_level' => 'All',
+        'display_name'  => 'Discord',
+        'icon' =>
+          'data:image/svg+xml,%3Csvg%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20245%20240%22%3E%3Cstyle%3E.st0%7Bfill%3A%237289DA%3B%7D%3C%2Fstyle%3E%3Cpath%20class%3D%22st0%22%20d%3D%22M104.4%20103.9c-5.7%200-10.2%205-10.2%2011.1s4.6%2011.1%2010.2%2011.1c5.7%200%2010.2-5%2010.2-11.1.1-6.1-4.5-11.1-10.2-11.1zM140.9%20103.9c-5.7%200-10.2%205-10.2%2011.1s4.6%2011.1%2010.2%2011.1c5.7%200%2010.2-5%2010.2-11.1s-4.5-11.1-10.2-11.1z%22%2F%3E%3Cpath%20class%3D%22st0%22%20d%3D%22M189.5%2020h-134C44.2%2020%2035%2029.2%2035%2040.6v135.2c0%2011.4%209.2%2020.6%2020.5%2020.6h113.4l-5.3-18.5%2012.8%2011.9%2012.1%2011.2%2021.5%2019V40.6c0-11.4-9.2-20.6-20.5-20.6zm-38.6%20130.6s-3.6-4.3-6.6-8.1c13.1-3.7%2018.1-11.9%2018.1-11.9-4.1%202.7-8%204.6-11.5%205.9-5%202.1-9.8%203.5-14.5%204.3-9.6%201.8-18.4%201.3-25.9-.1-5.7-1.1-10.6-2.7-14.7-4.3-2.3-.9-4.8-2-7.3-3.4-.3-.2-.6-.3-.9-.5-.2-.1-.3-.2-.4-.3-1.8-1-2.8-1.7-2.8-1.7s4.8%208%2017.5%2011.8c-3%203.8-6.7%208.3-6.7%208.3-22.1-.7-30.5-15.2-30.5-15.2%200-32.2%2014.4-58.3%2014.4-58.3%2014.4-10.8%2028.1-10.5%2028.1-10.5l1%201.2c-18%205.2-26.3%2013.1-26.3%2013.1s2.2-1.2%205.9-2.9c10.7-4.7%2019.2-6%2022.7-6.3.6-.1%201.1-.2%201.7-.2%206.1-.8%2013-1%2020.2-.2%209.5%201.1%2019.7%203.9%2030.1%209.6%200%200-7.9-7.5-24.9-12.7l1.4-1.6s13.7-.3%2028.1%2010.5c0%200%2014.4%2026.1%2014.4%2058.3%200%200-8.5%2014.5-30.6%2015.2z%22%2F%3E%3C%2Fsvg%3E'
+    };
+}
+
+1;

+ 60 - 0
t/Cpanel-iContact-Provider-Discord.t

@@ -0,0 +1,60 @@
+use strict;
+use warnings;
+
+use Cwd qw{abs_path};
+use File::Basename qw{dirname};
+use lib abs_path( dirname(__FILE__) . "/../lib" );
+
+use Test::More;
+use Test::Fatal;
+use Test::MockModule ();
+use Config::Simple   ();
+
+use Cpanel::HTTP::Client              ();
+use Cpanel::HTTP::Client::Response    ();
+use Cpanel::iContact::Provider::Discord ();
+
+plan tests => 2;
+
+# First, let's mock out the parent, and other stuff we wouldn't wanna do in a unit test
+subtest "Provider bits work as expected ('unit' test)" => sub {
+    my $text_scalar = 'lol, jk';
+    my $send_args   = { 'subject' => "[test.host.tld] YOUR COMIC BOOKS ARE DYING!!!1", 'text_body' => \$text_scalar, 'to' => [ 'SalinasPunishmentRoom', '@cPSaurus' ] };
+    my $contact_cfg = {};
+    my $ua_mocker = Test::MockModule->new("Cpanel::HTTP::Client");
+    $ua_mocker->mock( 'request' => sub { return bless {}, "Cpanel::HTTP::Client::Response"; } );
+    my $resp_mocker = Test::MockModule->new("Cpanel::HTTP::Client::Response");
+    $resp_mocker->mock( 'success' => sub { return 1; }, 'status' => sub { return 200; }, 'reason' => sub { return 'OK'; } );
+
+    isa_ok( my $spammer = Cpanel::iContact::Provider::Discord->new(), "Cpanel::iContact::Provider::Discord" );
+    is( exception { $spammer->send() }, undef, "send doesn't throw on GreatSuccess" );
+    $resp_mocker->mock( 'success' => sub { return 0; }, 'status' => sub { return 500; }, 'reason' => sub { return 'ENOHUGS'; } );
+    isnt( exception { $spammer->send() }, undef, "send throws whenever anything goes wrong" );
+};
+
+subtest "Can send a message to somewhere (systems level/integration test)" => sub {
+    SKIP: {
+        my $conf_file = abs_path( dirname(__FILE__) . "/../.discordtestrc" );
+        skip "Skipping functional testing, needful not supplied", 1 if !$ENV{'AUTHOR_TESTS'} || !-f $conf_file;
+        my $test_conf = { Config::Simple->import_from($conf_file)->vars() };
+        my $text_body = "This is a test of Cpanel::iContact::Provider::Discord. Please Ignore";
+        my %args = (
+            'to'        => [ $test_conf->{'CONTACTDISCORD'} ],
+            'subject'   => 'My Super cool test notification',
+            'text_body' => \$text_body,
+        );
+
+        {
+            no warnings qw{redefine once};
+            local *Cpanel::iContact::Provider::Discord::new = sub {
+                return bless {
+                    'contact' => $test_conf,
+                    'args'    => \%args,
+                }, $_[0];
+            };
+            my $spammer = Cpanel::iContact::Provider::Discord->new();
+            my $ex;
+            is( $ex = exception { $spammer->send() }, undef, "Didn't fail to send notification using full functional test" ) || diag explain $ex;
+        }
+    }
+};