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