File Coverage

blib/lib/App/Toot/Config.pm
Criterion Covered Total %
statement 9 35 25.7
branch 0 14 0.0
condition 0 6 0.0
subroutine 3 6 50.0
pod 1 1 100.0
total 13 62 20.9


line stmt bran cond sub pod time code
1             package App::Toot::Config;
2              
3 1     1   54 use strict;
  1         5  
  1         30  
4 1     1   4 use warnings;
  1         2  
  1         23  
5              
6 1     1   1327 use Config::Tiny;
  1         1119  
  1         370  
7              
8             our $VERSION = '0.04';
9              
10             sub load {
11 0     0 1   my $class = shift;
12 0           my $section = shift;
13              
14 0 0         if ( !defined $section ) {
15 0           die 'section is required';
16             }
17              
18 0           my $config = _load_and_verify();
19              
20 0 0         if ( !exists $config->{$section} ) {
21 0           die "$section section was not found in the config";
22             }
23              
24 0           return $config->{$section};
25             }
26              
27             sub _get_conf_dir {
28 0     0     my $name = 'toot';
29              
30 0           my $dir;
31 0 0 0       if ( $ENV{HOME} && -d "$ENV{HOME}/.config/$name" ) {
    0          
32 0           $dir = "$ENV{HOME}/.config";
33             }
34             elsif ( -d "/etc/$name" ) {
35 0           $dir = '/etc';
36             }
37             else {
38 0           die "error: unable to find config directory\n";
39             }
40              
41 0           return "$dir/$name";
42             }
43              
44             sub _load_and_verify {
45 0     0     my $rc = _get_conf_dir() . '/config.ini';
46              
47 0 0 0       unless ( -e $rc && -r $rc ) {
48 0           die "error: $rc does not exist or cannot be read\n";
49             }
50              
51 0           my $config = Config::Tiny->read($rc);
52              
53 0 0         unless ( defined $config->{'default'} ) {
54 0           die "default section in $rc is not defined\n";
55             }
56              
57 0           foreach my $section ( keys %$config ) {
58 0           foreach my $key (qw{ instance username client_id client_secret access_token }) {
59 0 0         unless ( defined $config->{$section}{$key} ) {
60 0           die "$key key for $section section in $rc is not defined\n";
61             }
62             }
63             }
64              
65 0           return $config;
66             }
67              
68             1;
69              
70             __END__
71              
72             =pod
73              
74             =head1 NAME
75              
76             App::Toot::Config - load and verify the config
77              
78             =head1 SYNOPSIS
79              
80             use App::Toot::Config;
81             my $config = App::Toot::Config->load( 'section name' );
82              
83             =head1 DESCRIPTION
84              
85             C<App::Toot::Config> loads settings for L<App::Toot>.
86              
87             =head1 SUBROUTINES
88              
89             =head2 load( 'section name' )
90              
91             Reads, verifies, and returns the config.
92              
93             =head3 ARGUMENTS
94              
95             The defined section name is required and dies if not found in the loaded config.
96              
97             =head3 RETURNS
98              
99             Returns a hashref of the loaded config for the defined section name.
100              
101             =head1 CONFIGURATION
102              
103             To post to Mastodon, you need to provide the account's oauth credentials in the file C<config.ini>.
104              
105             An example is provided as part of this distribution. The user running the L<toot> script, for example through cron, will need access to the configuration file.
106              
107             To set up the configuration file, copy C<config.ini.example> into one of the following locations:
108              
109             =over
110              
111             =item C<$ENV{HOME}/.config/toot/config.ini>
112              
113             =item C</etc/toot/config.ini>
114              
115             =back
116              
117             After creating the file, edit and update the values in the C<default> section to match the account's oauth credentials.
118              
119             [default]
120             instance = mastodon.social
121             username = youruser
122             client_id = OKE98_kdno_NOTAREALCLIENTID
123             client_secret = mkjklnv_NOTAREALCLIENTSECRET
124             access_token = jo83_NOTAREALACCESSTOKEN
125              
126             B<NOTE:> If the C<$ENV{HOME}/.config/toot/> directory exists, C<config.ini> will be loaded from there regardless of a config file in C</etc/toot/>.
127              
128             =head2 Required keys
129              
130             The following keys are required for each section:
131              
132             =over
133              
134             =item instance
135              
136             The Mastodon server name the account belongs to.
137              
138             =item username
139              
140             The account name for the Mastodon server defined in C<instance>.
141              
142             =item client_id
143              
144             The C<client_id> as provided for the C<username> on the C<instance>.
145              
146             =item client_secret
147              
148             The C<client_secret> as provided for the C<username> on the C<instance>.
149              
150             =item access_token
151              
152             The C<access_token> as provided for the C<username> on the C<instance>.
153              
154             =back
155              
156             =head2 Additional accounts
157              
158             Multiple accounts can be configured with different sections after the C<default> section.
159              
160             [default]
161             instance = mastodon.social
162             username = youruser
163             client_id = OKE98_kdno_NOTAREALCLIENTID
164             client_secret = mkjklnv_NOTAREALCLIENTSECRET
165             access_token = jo83_NOTAREALACCESSTOKEN
166             [development]
167             instance = botsin.space
168             username = yourdeveluser
169             client_id = Ijjkn_STILLNOTAREALCLIENTID
170             client_secret = u7hhd_STILLNOTAREALCLIENTSECRET
171             access_token = D873_SKILLNOTAREALACCESSTOKEN
172              
173             The section name, C<development> in the example above, can be named anything as long as it's unique with the other section names.
174              
175             =head1 COPYRIGHT AND LICENSE
176              
177             Copyright (c) 2023 Blaine Motsinger under the MIT license.
178              
179             =head1 AUTHOR
180              
181             Blaine Motsinger C<blaine@renderorange.com>
182              
183             =cut