| blib/lib/EBook/Gutenberg/Get.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 26 | 42 | 61.9 |
| branch | 0 | 8 | 0.0 |
| condition | 0 | 5 | 0.0 |
| subroutine | 9 | 10 | 90.0 |
| pod | 2 | 2 | 100.0 |
| total | 37 | 67 | 55.2 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package EBook::Gutenberg::Get; | ||||||
| 2 | 3 | 3 | 144577 | use 5.016; | |||
| 3 | 12 | ||||||
| 3 | our $VERSION = '1.00'; | ||||||
| 4 | 3 | 3 | 41 | use strict; | |||
| 3 | 5 | ||||||
| 3 | 95 | ||||||
| 5 | 3 | 3 | 14 | use warnings; | |||
| 3 | 4 | ||||||
| 3 | 157 | ||||||
| 6 | |||||||
| 7 | 3 | 3 | 15 | use Exporter 'import'; | |||
| 3 | 6 | ||||||
| 3 | 227 | ||||||
| 8 | our @EXPORT = qw(gutenberg_link gutenberg_get); | ||||||
| 9 | |||||||
| 10 | 3 | 3 | 653 | use File::Copy; | |||
| 3 | 7544 | ||||||
| 3 | 225 | ||||||
| 11 | 3 | 3 | 794 | use File::Fetch; | |||
| 3 | 125644 | ||||||
| 3 | 98 | ||||||
| 12 | 3 | 3 | 19 | use File::Spec; | |||
| 3 | 5 | ||||||
| 3 | 82 | ||||||
| 13 | 3 | 3 | 18 | use File::Temp qw(tempdir); | |||
| 3 | 5 | ||||||
| 3 | 2433 | ||||||
| 14 | |||||||
| 15 | our %FORMATS = ( | ||||||
| 16 | 'html' => { | ||||||
| 17 | link => sub { | ||||||
| 18 | "https://www.gutenberg.org/ebooks/$_[0].html.images" | ||||||
| 19 | }, | ||||||
| 20 | suffix => 'html', | ||||||
| 21 | }, | ||||||
| 22 | 'epub3' => { | ||||||
| 23 | link => sub { | ||||||
| 24 | "https://www.gutenberg.org/ebooks/$_[0].epub3.images" | ||||||
| 25 | }, | ||||||
| 26 | suffix => 'epub', | ||||||
| 27 | }, | ||||||
| 28 | 'epub' => { | ||||||
| 29 | link => sub { | ||||||
| 30 | "https://www.gutenberg.org/ebooks/$_[0].epub.images" | ||||||
| 31 | }, | ||||||
| 32 | suffix => 'epub', | ||||||
| 33 | }, | ||||||
| 34 | 'epub-noimages' => { | ||||||
| 35 | link => sub { | ||||||
| 36 | "https://www.gutenberg.org/ebooks/$_[0].epub.noimages" | ||||||
| 37 | }, | ||||||
| 38 | suffix => 'epub', | ||||||
| 39 | }, | ||||||
| 40 | 'kindle' => { | ||||||
| 41 | link => sub { | ||||||
| 42 | "https://www.gutenberg.org/ebooks/$_[0].kf8.images" | ||||||
| 43 | }, | ||||||
| 44 | suffix => 'azw3', | ||||||
| 45 | }, | ||||||
| 46 | 'mobi' => { | ||||||
| 47 | link => sub { | ||||||
| 48 | "https://www.gutenberg.org/ebooks/$_[0].kindle.images" | ||||||
| 49 | }, | ||||||
| 50 | suffix => 'mobi', | ||||||
| 51 | }, | ||||||
| 52 | 'text' => { | ||||||
| 53 | link => sub { | ||||||
| 54 | "https://www.gutenberg.org/ebooks/$_[0].txt.utf-8" | ||||||
| 55 | }, | ||||||
| 56 | suffix => 'txt', | ||||||
| 57 | }, | ||||||
| 58 | 'zip' => { | ||||||
| 59 | link => sub { | ||||||
| 60 | "https://www.gutenberg.org/cache/epub/$_[0]/pg$_[0]-h.zip" | ||||||
| 61 | }, | ||||||
| 62 | suffix => 'zip', | ||||||
| 63 | }, | ||||||
| 64 | ); | ||||||
| 65 | |||||||
| 66 | sub gutenberg_link { | ||||||
| 67 | |||||||
| 68 | 8 | 8 | 1 | 263421 | my $id = shift; | ||
| 69 | 8 | 18 | my $fmt = shift; | ||||
| 70 | |||||||
| 71 | 8 | 38 | return $FORMATS{ $fmt }->{ link }($id); | ||||
| 72 | |||||||
| 73 | } | ||||||
| 74 | |||||||
| 75 | sub gutenberg_get { | ||||||
| 76 | |||||||
| 77 | 0 | 0 | 1 | my $id = shift; | |||
| 78 | 0 | my $param = shift; | |||||
| 79 | |||||||
| 80 | 0 | 0 | unless ($id =~ /^\d+$/) { | ||||
| 81 | 0 | die "id must be an integar\n"; | |||||
| 82 | } | ||||||
| 83 | |||||||
| 84 | 0 | 0 | my $fmt = $param->{ fmt } // 'epub3'; | ||||
| 85 | 0 | 0 | my $to = $param->{ to } // "$id.*"; | ||||
| 86 | |||||||
| 87 | 0 | $to =~ s/\.\*$/\.$FORMATS{ $fmt }->{ suffix }/; | |||||
| 88 | |||||||
| 89 | 0 | 0 | if (-d $to) { | ||||
| 90 | 0 | die "Cannot download file to $to: is a directory\n"; | |||||
| 91 | } | ||||||
| 92 | |||||||
| 93 | 0 | my $link = gutenberg_link($id, $fmt); | |||||
| 94 | |||||||
| 95 | 0 | my $tmp = tempdir(CLEANUP => 1); | |||||
| 96 | |||||||
| 97 | 0 | my $ff = File::Fetch->new(uri => $link); | |||||
| 98 | |||||||
| 99 | 0 | 0 | my $fetch = $ff->fetch(to => $tmp) | ||||
| 100 | or die $ff->error; | ||||||
| 101 | |||||||
| 102 | 0 | 0 | move($fetch, $to) | ||||
| 103 | or die "Failed to move $fetch to $to: $!\n"; | ||||||
| 104 | |||||||
| 105 | 0 | rmdir $tmp; | |||||
| 106 | |||||||
| 107 | 0 | return $to; | |||||
| 108 | |||||||
| 109 | } | ||||||
| 110 | |||||||
| 111 | 1; | ||||||
| 112 | |||||||
| 113 | =head1 NAME | ||||||
| 114 | |||||||
| 115 | EBook::Gutenberg::Get - Fetch ebooks from Project Gutenberg | ||||||
| 116 | |||||||
| 117 | =head1 SYNOPSIS | ||||||
| 118 | |||||||
| 119 | use EBook::Gutenberg::Get; | ||||||
| 120 | |||||||
| 121 | my $ebook = gutenberg_get($id); | ||||||
| 122 | |||||||
| 123 | =head1 DESCRIPTION | ||||||
| 124 | |||||||
| 125 | B |
||||||
| 126 | downloading ebooks from Project Gutenberg. This is developer documentation, | ||||||
| 127 | for L |
||||||
| 128 | |||||||
| 129 | Note that this module is not designed to perform bulk downloading/scraping. | ||||||
| 130 | Attempting to use this module to do so may result in Project Gutenberg banning | ||||||
| 131 | you from their site. You have been warned. | ||||||
| 132 | |||||||
| 133 | =head1 SUBROUTINES | ||||||
| 134 | |||||||
| 135 | The following subroutines are exported by C |
||||||
| 136 | automatically. | ||||||
| 137 | |||||||
| 138 | =over 4 | ||||||
| 139 | |||||||
| 140 | =item $get = gutenberg_get($id, [\%param]) | ||||||
| 141 | |||||||
| 142 | Fetches an ebook from Project Gutenberg. C<$id> is the ID of the ebook to | ||||||
| 143 | fetch. C<\%params> is a hash ref of extra parameters to configure the download | ||||||
| 144 | process. | ||||||
| 145 | |||||||
| 146 | The following are valid parameters: | ||||||
| 147 | |||||||
| 148 | =over 4 | ||||||
| 149 | |||||||
| 150 | =item to | ||||||
| 151 | |||||||
| 152 | Path to write downloaded file to. Defaults to C<'$id.*'>. If the provided path | ||||||
| 153 | has a C<'.*'> suffix, the C<'.*'> will be substituted by the ebook format's | ||||||
| 154 | file suffix. | ||||||
| 155 | |||||||
| 156 | =item fmt | ||||||
| 157 | |||||||
| 158 | Format of ebook to download. The following are valid options: | ||||||
| 159 | |||||||
| 160 | =over 4 | ||||||
| 161 | |||||||
| 162 | =item html | ||||||
| 163 | |||||||
| 164 | =item epub3 | ||||||
| 165 | |||||||
| 166 | =item epub | ||||||
| 167 | |||||||
| 168 | =item epub-noimages | ||||||
| 169 | |||||||
| 170 | =item kindle | ||||||
| 171 | |||||||
| 172 | =item mobi | ||||||
| 173 | |||||||
| 174 | =item text | ||||||
| 175 | |||||||
| 176 | =item zip | ||||||
| 177 | |||||||
| 178 | =back | ||||||
| 179 | |||||||
| 180 | Defaults to C<'epub3'>. | ||||||
| 181 | |||||||
| 182 | =back | ||||||
| 183 | |||||||
| 184 | =item $link = gutenberg_link($id, $fmt) | ||||||
| 185 | |||||||
| 186 | Returns the download link of an ebook. C<$id> is the ID of the ebook. C<$fmt> | ||||||
| 187 | is the ebook format. | ||||||
| 188 | |||||||
| 189 | =back | ||||||
| 190 | |||||||
| 191 | =head1 GLOBAL VARIABLES | ||||||
| 192 | |||||||
| 193 | =over 4 | ||||||
| 194 | |||||||
| 195 | =item %EBook::Gutenberg::FORMATS | ||||||
| 196 | |||||||
| 197 | Hash of valid ebook formats and a hash ref of some format data. See the | ||||||
| 198 | documentation for C |
||||||
| 199 | |||||||
| 200 | The format hash ref has this format: | ||||||
| 201 | |||||||
| 202 | =over 4 | ||||||
| 203 | |||||||
| 204 | =item link | ||||||
| 205 | |||||||
| 206 | Subroutine reference that, when given an ebook ID, returns a download link to | ||||||
| 207 | that ebook. | ||||||
| 208 | |||||||
| 209 | =item suffix | ||||||
| 210 | |||||||
| 211 | The default file suffix to use with the format. | ||||||
| 212 | |||||||
| 213 | =back | ||||||
| 214 | |||||||
| 215 | =back | ||||||
| 216 | |||||||
| 217 | =head1 AUTHOR | ||||||
| 218 | |||||||
| 219 | Written by Samuel Young, E |
||||||
| 220 | |||||||
| 221 | This project's source can be found on its | ||||||
| 222 | L |
||||||
| 223 | requests are welcome! | ||||||
| 224 | |||||||
| 225 | =head1 COPYRIGHT | ||||||
| 226 | |||||||
| 227 | Copyright (C) 2025 Samuel Young | ||||||
| 228 | |||||||
| 229 | This program is free software: you can redistribute it and/or modify | ||||||
| 230 | it under the terms of the GNU General Public License as published by | ||||||
| 231 | the Free Software Foundation, either version 3 of the License, or | ||||||
| 232 | (at your option) any later version. | ||||||
| 233 | |||||||
| 234 | =head1 SEE ALSO | ||||||
| 235 | |||||||
| 236 | L |
||||||
| 237 | |||||||
| 238 | =cut | ||||||
| 239 | |||||||
| 240 | # vim: expandtab shiftwidth=4 |