File Coverage

blib/lib/Bot/IRC/Store/SQLite.pm
Criterion Covered Total %
statement 27 39 69.2
branch 3 10 30.0
condition 1 7 14.2
subroutine 8 10 80.0
pod 2 4 50.0
total 41 70 58.5


line stmt bran cond sub pod time code
1             # ABSTRACT: Bot::IRC persistent data storage with SQLite
2              
3             use 5.014;
4 1     1   171624 use exact;
  1         7  
5 1     1   356  
  1         27563  
  1         4  
6             use DBI;
7 1     1   3025 use DBD::SQLite;
  1         13200  
  1         46  
8 1     1   695 use JSON::XS;
  1         7013  
  1         30  
9 1     1   521  
  1         3675  
  1         9685  
10             our $VERSION = '1.39'; # VERSION
11              
12             my ($bot) = @_;
13             my $obj = __PACKAGE__->new($bot);
14 1     1 0 305  
15 1         4 $bot->subs( 'store' => sub { return $obj } );
16             $bot->register('Bot::IRC::Store');
17 1     2   19 }
  2         573  
18 1         3  
19             my ( $class, $bot ) = @_;
20             my $self = bless( {}, $class );
21              
22 2     2 0 28 $self->{file} = $bot->vars('store') || 'store.sqlite';
23 2         4 my $pre_exists = ( -f $self->{file} ) ? 1 : 0;
24              
25 2   50     7 $self->{dbh} = DBI->connect( 'dbi:SQLite:dbname=' . $self->{file} ) or die "$@\n";
26 2 50       49  
27             $self->{dbh}->do(q{
28 2 50       15 CREATE TABLE IF NOT EXISTS bot_store (
29             id INTEGER PRIMARY KEY ASC,
30 2 50       37 namespace TEXT,
31             key TEXT,
32             value TEXT
33             )
34             }) unless ($pre_exists);
35              
36             $self->{json} = JSON::XS->new->ascii;
37              
38             return $self;
39 2         14 }
40              
41 2         6 my ( $self, $key ) = @_;
42             my $namespace = ( caller() )[0];
43             my $value;
44              
45 0     0 1   try {
46 0           my $sth = $self->{dbh}->prepare_cached(q{
47 0           SELECT value FROM bot_store WHERE namespace = ? AND key = ?
48             });
49             $sth->execute( $namespace, $key ) or die $self->{dbh}->errstr;
50             $value = $sth->fetchrow_array;
51             $sth->finish;
52             }
53             catch {
54             my $e = $_ || $@;
55             warn "Store get error with $namespace (likely an IRC::Store::SQLite issue); key = $key; error = $e\n";
56             };
57 0            
58             if ($value) {
59             $value = $self->{json}->decode($value) || undef;
60             $value = $value->{value} if ( ref $value eq 'HASH' and exists $value->{value} );
61             }
62 0 0          
63 0   0       return $value;
64 0 0 0       }
65              
66             my ( $self, $key, $value ) = @_;
67 0           my $namespace = ( caller() )[0];
68              
69             try {
70             $self->{dbh}->prepare_cached(q{
71 0     0 1   DELETE FROM bot_store WHERE namespace = ? AND key = ?
72 0           })->execute( $namespace, $key ) or die $self->{dbh}->errstr;
73              
74             $self->{dbh}->prepare_cached(q{
75             INSERT INTO bot_store ( namespace, key, value ) VALUES ( ?, ?, ? )
76             })->execute(
77             $namespace,
78             $key,
79             $self->{json}->encode( { value => $value } ),
80             ) or die $self->{dbh}->errstr;
81             }
82             catch {
83             my $e = $_ || $@;
84             warn "Store set error with $namespace (likely an IRC::Store::SQLite issue); key = $key; error = $e\n";
85             };
86              
87 0           return $self;
88             }
89              
90             1;
91              
92 0            
93             =pod
94              
95             =encoding UTF-8
96              
97             =head1 NAME
98              
99             Bot::IRC::Store::SQLite - Bot::IRC persistent data storage with SQLite
100              
101             =head1 VERSION
102              
103             version 1.39
104              
105             =head1 SYNOPSIS
106              
107             use Bot::IRC;
108              
109             Bot::IRC->new(
110             connect => { server => 'irc.perl.org' },
111             plugins => ['Store::SQLite'],
112             vars => { store => 'bot.sqlite' },
113             )->run;
114              
115             =head1 DESCRIPTION
116              
117             This L<Bot::IRC> plugin provides a persistent storage mechanism with a SQLite
118             database file. By default, it's the "store.sqlite" file, but this can be changed
119             with the C<vars>, C<store> value.
120              
121             =head1 EXAMPLE USE
122              
123             This plugin adds a single sub to the bot object called C<store()>. Calling it
124             will return a storage object which itself provides C<get()> and C<set()>
125             methods. These operate just like you would expect.
126              
127             =head2 set
128              
129             $bot->store->set( user => { nick => 'gryphon', score => 42 } );
130              
131             =head2 get
132              
133             my $score = $bot->store->set('user')->{score};
134              
135             =head2 SEE ALSO
136              
137             L<Bot::IRC>
138              
139             =for Pod::Coverage init new
140              
141             =head1 AUTHOR
142              
143             Gryphon Shafer <gryphon@cpan.org>
144              
145             =head1 COPYRIGHT AND LICENSE
146              
147             This software is Copyright (c) 2016-2050 by Gryphon Shafer.
148              
149             This is free software, licensed under:
150              
151             The Artistic License 2.0 (GPL Compatible)
152              
153             =cut