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