File Coverage

blib/lib/App/RoboBot/Config.pm
Criterion Covered Total %
statement 15 17 88.2
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 21 23 91.3


line stmt bran cond sub pod time code
1             package App::RoboBot::Config;
2             $App::RoboBot::Config::VERSION = '4.002';
3 5     5   50 use v5.20;
  5         11  
4              
5 5     5   24 use namespace::autoclean;
  5         7  
  5         46  
6              
7 5     5   476 use Moose;
  5         7  
  5         39  
8 5     5   25013 use MooseX::SetOnce;
  5         7  
  5         130  
9              
10 5     5   2453 use Config::Any::Merge;
  5         22507  
  5         142  
11 5     5   937 use DBD::Pg;
  0            
  0            
12             use DBIx::DataStore;
13             use File::HomeDir;
14             use Try::Tiny;
15              
16             use App::RoboBot::NetworkFactory;
17             use App::RoboBot::Channel;
18             use App::RoboBot::Nick;
19              
20             has 'bot' => (
21             is => 'ro',
22             isa => 'App::RoboBot',
23             required => 1,
24             );
25              
26             has 'config_paths' => (
27             is => 'rw',
28             isa => 'ArrayRef[Str]',
29             traits => [qw( SetOnce )],
30             predicate => 'has_config_paths',
31             );
32              
33             has 'config' => (
34             is => 'rw',
35             isa => 'HashRef',
36             predicate => 'has_config',
37             );
38              
39             has 'networks' => (
40             is => 'rw',
41             isa => 'HashRef',
42             );
43              
44             has 'channels' => (
45             is => 'rw',
46             isa => 'ArrayRef[App::RoboBot::Channel]',
47             );
48              
49             has 'plugins' => (
50             is => 'rw',
51             isa => 'HashRef',
52             default => sub { {} },
53             );
54              
55             has 'db' => (
56             is => 'rw',
57             isa => 'DBIx::DataStore',
58             traits => [qw( SetOnce )],
59             );
60              
61             sub load_config {
62             my ($self) = @_;
63              
64             try {
65             unless ($self->has_config) {
66             $self->locate_config unless $self->has_config_paths;
67              
68             if (my $cfg = Config::Any::Merge->load_files({ files => $self->config_paths, use_ext => 1, override => 1 })) {
69             $self->config($cfg);
70             } else {
71             die "Could not load configuration files: " . join(', ', @{$self->config_paths});
72             }
73             }
74              
75             $self->validate_database;
76             $self->validate_globals;
77             $self->validate_networks;
78             $self->validate_plugins;
79              
80             $self->bot->networks([ values %{$self->networks} ]);
81             } catch {
82             die "Could not load and validate configuration: $_";
83             };
84             }
85              
86             sub locate_config {
87             my ($self) = @_;
88              
89             my $home = File::HomeDir->my_home();
90             my @exts = qw( conf yml yaml json xml ini );
91             my @bases = ("$home/.lispy/lispy.", "$home/.lispy.", "/etc/lispy.");
92              
93             my @configs;
94              
95             foreach my $base (@bases) {
96             foreach my $ext (@exts) {
97             push(@configs, $base . $ext);
98             }
99             }
100              
101             my @found;
102              
103             CONFIG_FILE:
104             foreach my $path (@configs) {
105             if (-f $path && -r _) {
106             push(@found, $path);
107             }
108             }
109              
110             $self->config_paths([reverse @found]);
111              
112             die "Unable to locate a configuration file!" unless $self->has_config_paths;
113             }
114              
115             sub validate_globals {
116             my ($self) = @_;
117              
118             my %global = (
119             nick => 'lispy',
120             );
121              
122             $self->config->{'global'} = \%global unless exists $self->config->{'global'};
123              
124             foreach my $k (keys %global) {
125             $self->config->{'global'}{$k} = $global{$k} unless exists $self->config->{'global'}{$k};
126             }
127              
128             $self->config->{'global'}{'nick'} = App::RoboBot::Nick->new(
129             config => $self,
130             name => $self->config->{'global'}{'nick'}
131             );
132             }
133              
134             sub validate_database {
135             my ($self) = @_;
136              
137             my %database = (
138             name => 'robobot',
139             );
140              
141             $self->config->{'database'} = \%database unless exists $self->config->{'database'};
142              
143             foreach my $k (keys %database) {
144             $self->config->{'database'}{$k} = $database{$k} unless exists $self->config->{'database'}{$k};
145             }
146              
147             if (exists $self->config->{'database'}{'primary'} && ref($self->config->{'database'}{'primary'}) eq 'HASH') {
148             $self->db(DBIx::DataStore->new({ config => $self->config->{'database'} })) or die "Could not validate explicit database connection!";
149             } else {
150             $self->db(DBIx::DataStore->new($self->config->{'database'}{'name'})) or die "Could not validate named database connection!";
151             }
152              
153             $self->bot->migrate_database;
154             }
155              
156             sub validate_networks {
157             my ($self) = @_;
158              
159             my @networks;
160             my @channels;
161              
162             my $nfactory = App::RoboBot::NetworkFactory->new(
163             bot => $self->bot,
164             config => $self,
165             nick => $self->config->{'global'}{'nick'},
166             );
167              
168             foreach my $network_name (keys %{$self->config->{'network'}}) {
169             my $net_cfg = $self->config->{'network'}{$network_name};
170              
171             # Do not load (and eventually connect to) the network if the 'enabled'
172             # property exists and is set to a falsey value.
173             next if exists $self->config->{'network'}{$network_name}{'enabled'}
174             && !$self->config->{'network'}{$network_name}{'enabled'};
175              
176             push(@networks, $nfactory->create($network_name, $net_cfg));
177              
178             my @network_channels;
179              
180             # Coerce channel list into an arrayref if only a single channel is
181             # listed for this network.
182             $net_cfg->{'channel'} = [] unless exists $net_cfg->{'channel'};
183             $net_cfg->{'channel'} = [$net_cfg->{'channel'}] if ref($net_cfg->{'channel'}) ne 'ARRAY';
184              
185             foreach my $chan_name (@{$net_cfg->{'channel'}}) {
186             push(@network_channels, App::RoboBot::Channel->new( config => $self, network => $networks[-1], name => $chan_name));
187             push(@channels, $network_channels[-1]);
188             }
189              
190             $networks[-1]->channels([@network_channels]);
191             }
192              
193             $self->networks({ map { $_->name => $_ } @networks });
194             $self->channels(\@channels);
195             }
196              
197             sub validate_plugins {
198             my ($self) = @_;
199              
200             foreach my $plugin_name (keys %{$self->config->{'plugin'}}) {
201             $self->plugins->{lc($plugin_name)} = $self->config->{'plugin'}{$plugin_name};
202             }
203             }
204              
205             __PACKAGE__->meta->make_immutable;
206              
207             1;