Adding Farmacia de Guardia.
This commit is contained in:
parent
455afc62f5
commit
af83dabf8c
1
Build.PL
1
Build.PL
@ -17,6 +17,7 @@ my $build = Module::Build->new(
|
|||||||
'DBD::Pg' => 0,
|
'DBD::Pg' => 0,
|
||||||
'DateTime::Format::ISO8601.pm' => 0,
|
'DateTime::Format::ISO8601.pm' => 0,
|
||||||
'DateTime::Format::Mail.pm' => 0,
|
'DateTime::Format::Mail.pm' => 0,
|
||||||
|
'DateTime::Format::Pg' => 0,
|
||||||
'SVG' => 0,
|
'SVG' => 0,
|
||||||
'XML::Twig' => 0,
|
'XML::Twig' => 0,
|
||||||
'JSON' => 0,
|
'JSON' => 0,
|
||||||
|
15
content/posts/0000036-farmacia-de-guardia.xml
Normal file
15
content/posts/0000036-farmacia-de-guardia.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<post>
|
||||||
|
<author>Burguillos.info</author>
|
||||||
|
<date>2023-09-07T16:11:00+00:00</date>
|
||||||
|
<title>Farmacia de Guardia en Burguillos.</title>
|
||||||
|
<ogdesc>Farmacia de Guardia en Burguillos.</ogdesc>
|
||||||
|
<img src="/img/farmacia.webp"/>
|
||||||
|
<category>index</category>
|
||||||
|
<slug>farmacia-guardia</slug>
|
||||||
|
<content>
|
||||||
|
<img alt="Imagen de cruz de Farmacia" src="/img/farmacia.webp"/>
|
||||||
|
<p>Este artículo se rellena automáticamente con los datos de la Farmacia de Guardia, tu navegador o móvil debe soportar Javascript para que funcione.</p>
|
||||||
|
|
||||||
|
<p>La farmacia de guardia esta semana y hasta la siguiente vez que sean las 9:30 un lunes es <b id="farmacia-name"></b> se encuentra ubicada en <b id="farmacia-address"></b>.</p>
|
||||||
|
</content>
|
||||||
|
</post>
|
@ -10,6 +10,7 @@ window.onload = () => {
|
|||||||
const mobile_foldable = document.querySelector('nav.mobile-foldable');
|
const mobile_foldable = document.querySelector('nav.mobile-foldable');
|
||||||
const tables = document.querySelectorAll('table')
|
const tables = document.querySelectorAll('table')
|
||||||
|
|
||||||
|
fillFarmaciaGuardia();
|
||||||
loadAd()
|
loadAd()
|
||||||
addEasterEggAnimation()
|
addEasterEggAnimation()
|
||||||
|
|
||||||
@ -39,6 +40,26 @@ window.onload = () => {
|
|||||||
addListenersSearch()
|
addListenersSearch()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function fillFarmaciaGuardia() {
|
||||||
|
const farmaciaName = document.querySelector('#farmacia-name');
|
||||||
|
const farmaciaAddress = document.querySelector('#farmacia-address');
|
||||||
|
if (farmaciaName !== null || farmaciaAddress !== null) {
|
||||||
|
const port = _port()
|
||||||
|
const url = new URL(window.location.protocol
|
||||||
|
+ "//"
|
||||||
|
+ window.location.hostname
|
||||||
|
+ port
|
||||||
|
+ '/farmacia-guardia.json');
|
||||||
|
fetch(url).then(async (res) => {
|
||||||
|
const farmacia = await res.json()
|
||||||
|
if (farmaciaName !== null) {
|
||||||
|
farmaciaName.innerText = farmacia.name;
|
||||||
|
farmaciaAddress.innerText = farmacia.address;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function addListenersSearch() {
|
function addListenersSearch() {
|
||||||
if (searchMobile !== null) {
|
if (searchMobile !== null) {
|
||||||
const searchIcon = searchMobile.querySelector('div.search-icon')
|
const searchIcon = searchMobile.querySelector('div.search-icon')
|
||||||
@ -62,6 +83,14 @@ function addListenersSearch() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _port() {
|
||||||
|
let port = window.location.port;
|
||||||
|
if (port !== '') {
|
||||||
|
port = ':' + port
|
||||||
|
}
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
function onSearchChange() {
|
function onSearchChange() {
|
||||||
const search = document.querySelector('div.search-overlay div.search input');
|
const search = document.querySelector('div.search-overlay div.search input');
|
||||||
const searchResults = document.querySelector('div.search-overlay div.search-results');
|
const searchResults = document.querySelector('div.search-overlay div.search-results');
|
||||||
@ -70,10 +99,7 @@ function onSearchChange() {
|
|||||||
}
|
}
|
||||||
const query = search.value;
|
const query = search.value;
|
||||||
fakeSearchInput.value = search.value
|
fakeSearchInput.value = search.value
|
||||||
let port = window.location.port;
|
const port = _port()
|
||||||
if (port !== '') {
|
|
||||||
port = ':' + port
|
|
||||||
}
|
|
||||||
const url = new URL(window.location.protocol
|
const url = new URL(window.location.protocol
|
||||||
+ "//"
|
+ "//"
|
||||||
+ window.location.hostname
|
+ window.location.hostname
|
||||||
|
@ -52,6 +52,7 @@ sub startup ($self) {
|
|||||||
# $r->get('/:post')->to('Page#post');
|
# $r->get('/:post')->to('Page#post');
|
||||||
$r->get('/stats')->to('Metrics#stats');
|
$r->get('/stats')->to('Metrics#stats');
|
||||||
$r->get('/search.json')->to('Search#search');
|
$r->get('/search.json')->to('Search#search');
|
||||||
|
$r->get('/farmacia-guardia.json')->to('FarmaciaGuardia#current');
|
||||||
$r->get('/<:category>.rss')->to('Page#category_rss');
|
$r->get('/<:category>.rss')->to('Page#category_rss');
|
||||||
$r->get('/:category_slug/atributo/<:attribute_slug>-preview.png')->to('Attribute#get_attribute_preview');
|
$r->get('/:category_slug/atributo/<:attribute_slug>-preview.png')->to('Attribute#get_attribute_preview');
|
||||||
$r->get('/:category_slug/atributo/:attribute_slug')->to('Attribute#get');
|
$r->get('/:category_slug/atributo/:attribute_slug')->to('Attribute#get');
|
||||||
|
@ -60,7 +60,7 @@ sub get_rand_ad($self, $array) {
|
|||||||
my $max_weight = $self->sum_weights($array);
|
my $max_weight = $self->sum_weights($array);
|
||||||
my $rand = int(rand() * $max_weight);
|
my $rand = int(rand() * $max_weight);
|
||||||
my $sum_weight = 0;
|
my $sum_weight = 0;
|
||||||
for my $ad (@$array) {
|
for my $ad (@$valid_ads) {
|
||||||
$sum_weight += $ad->weight;
|
$sum_weight += $ad->weight;
|
||||||
if ($rand < $sum_weight) {
|
if ($rand < $sum_weight) {
|
||||||
return $ad;
|
return $ad;
|
||||||
|
@ -43,6 +43,12 @@ sub MIGRATIONS {
|
|||||||
\&_populate_locations,
|
\&_populate_locations,
|
||||||
\&_populate_locations,
|
\&_populate_locations,
|
||||||
\&_populate_locations,
|
\&_populate_locations,
|
||||||
|
'CREATE TABLE farmacia_guardia (
|
||||||
|
uuid UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||||
|
date timestamp NOT NULL,
|
||||||
|
id_farmacia TEXT NOT NULL
|
||||||
|
);',
|
||||||
|
'CREATE INDEX farmacia_guardia_index on farmacia_guardia (date, id_farmacia, uuid);',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
lib/BurguillosInfo/Farmacia.pm
Normal file
20
lib/BurguillosInfo/Farmacia.pm
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package BurguillosInfo::Farmacia;
|
||||||
|
|
||||||
|
use v5.36.0;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use utf8;
|
||||||
|
|
||||||
|
use Moo::Role;
|
||||||
|
|
||||||
|
requires qw(id name address);
|
||||||
|
|
||||||
|
sub serialize ($self) {
|
||||||
|
return {
|
||||||
|
id => $self->id,
|
||||||
|
name => $self->name,
|
||||||
|
address => $self->address,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
1;
|
141
lib/BurguillosInfo/FarmaciaGuardia.pm
Normal file
141
lib/BurguillosInfo/FarmaciaGuardia.pm
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package BurguillosInfo::FarmaciaGuardia;
|
||||||
|
|
||||||
|
use v5.36.0;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use utf8;
|
||||||
|
|
||||||
|
use feature 'signatures';
|
||||||
|
|
||||||
|
use Data::Dumper;
|
||||||
|
|
||||||
|
use Moo;
|
||||||
|
use DateTime;
|
||||||
|
use DateTime::Format::Pg;
|
||||||
|
|
||||||
|
use Mojo::UserAgent;
|
||||||
|
|
||||||
|
use BurguillosInfo::Farmacias;
|
||||||
|
use BurguillosInfo::Farmacias::CruzDeLaErmita;
|
||||||
|
use BurguillosInfo::Farmacias::Morera;
|
||||||
|
|
||||||
|
has _app => ( is => 'lazy', );
|
||||||
|
has _db => ( is => 'lazy' );
|
||||||
|
|
||||||
|
sub _build__app {
|
||||||
|
require BurguillosInfo;
|
||||||
|
return BurguillosInfo->new;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_current ($self) {
|
||||||
|
my $date_search = $self->_get_search_date;
|
||||||
|
my $farmacia_db = $self->_search_horario_db($date_search);
|
||||||
|
if (defined $farmacia_db) {
|
||||||
|
return $farmacia_db;
|
||||||
|
}
|
||||||
|
my $farmacia;
|
||||||
|
eval {
|
||||||
|
$farmacia = $self->_request_horario_internet($date_search);
|
||||||
|
};
|
||||||
|
if (!defined $farmacia) {
|
||||||
|
die "API possibly broken for Farmacia de Guardia. $@";
|
||||||
|
}
|
||||||
|
$self->_register_farmacia($date_search, $farmacia);
|
||||||
|
return $farmacia;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _register_farmacia($self, $date_search, $farmacia) {
|
||||||
|
my $f = DateTime::Format::Pg->new;
|
||||||
|
my $dbh = $self->_db;
|
||||||
|
$dbh->do(<<'EOF', undef, $f->format_datetime($date_search), $farmacia->id);
|
||||||
|
INSERT INTO farmacia_guardia (date, id_farmacia) VALUES (?, ?);
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _search_horario_db ( $self, $date_search ) {
|
||||||
|
my $f = DateTime::Format::Pg->new;
|
||||||
|
my $db = $self->_db;
|
||||||
|
$date_search = $date_search->clone;
|
||||||
|
$date_search->set_time_zone('UTC');
|
||||||
|
my $start_farmacia_week = $self->_get_start_date_week($date_search);
|
||||||
|
my $end_farmacia_week = $self->_get_end_date_week($date_search);
|
||||||
|
my $horarios = $db->selectall_arrayref(
|
||||||
|
<<'EOF', { Slice => {} }, $f->format_datetime($start_farmacia_week), $f->format_datetime($end_farmacia_week) );
|
||||||
|
SELECT id_farmacia from farmacia_guardia where date > ? and date < ?;
|
||||||
|
EOF
|
||||||
|
if (!scalar @$horarios) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
my $id = $horarios->[0]{id_farmacia};
|
||||||
|
return BurguillosInfo::Farmacias->new->by_id($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _request_horario_internet ( $self, $date_search ) {
|
||||||
|
my $ua = $self->_ua;
|
||||||
|
my $result = $ua->get(
|
||||||
|
'http://www.farmaciacruzdelaermita.com/index.php/component/dpcalendar/events',
|
||||||
|
form => {
|
||||||
|
limit => 0,
|
||||||
|
compact => 0,
|
||||||
|
my => 0,
|
||||||
|
format => 'raw',
|
||||||
|
ids => 10,
|
||||||
|
'date-start' => $date_search->epoch,
|
||||||
|
'date-end' => $date_search->epoch,
|
||||||
|
_ => $date_search->epoch * 1000,
|
||||||
|
}
|
||||||
|
)->result;
|
||||||
|
my $json;
|
||||||
|
eval { $json = $result->json; };
|
||||||
|
if ($@) {
|
||||||
|
die "Unable to recover data of Farmacia de Guardia $@.";
|
||||||
|
}
|
||||||
|
my $data;
|
||||||
|
eval { $data = $json->[0]{data}; };
|
||||||
|
if ( $@ || !defined $data ) {
|
||||||
|
die "Unable to get data of calendar.";
|
||||||
|
}
|
||||||
|
if ( scalar @$data ) {
|
||||||
|
return BurguillosInfo::Farmacias::CruzDeLaErmita->new;
|
||||||
|
}
|
||||||
|
return BurguillosInfo::Farmacias::Morera->new;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _ua {
|
||||||
|
return Mojo::UserAgent->new;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _get_search_date ($self) {
|
||||||
|
my $current_date = DateTime->now;
|
||||||
|
my $date_search = $current_date->clone;
|
||||||
|
if ( $date_search < $self->_get_start_date_week($current_date) ) {
|
||||||
|
$date_search = $date_search->add( days => -1 );
|
||||||
|
}
|
||||||
|
return $date_search;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _get_end_date_week ( $self, $date_search ) {
|
||||||
|
my $start_farmacia_week = $self->_get_start_date_week($date_search);
|
||||||
|
my $end_farmacia_week = $start_farmacia_week->clone->add( weeks => 1 );
|
||||||
|
$end_farmacia_week->set_time_zone('Europe/Madrid');
|
||||||
|
$end_farmacia_week->set_hour(9);
|
||||||
|
$end_farmacia_week->set_minute(30);
|
||||||
|
$end_farmacia_week->set_time_zone('UTC');
|
||||||
|
return $end_farmacia_week;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _get_start_date_week ( $self, $date_search ) {
|
||||||
|
my $start_farmacia_week = $date_search->clone->truncate( to => 'week' );
|
||||||
|
$start_farmacia_week->set_time_zone('Europe/Madrid');
|
||||||
|
$start_farmacia_week->set_hour(9);
|
||||||
|
$start_farmacia_week->set_minute(30);
|
||||||
|
$start_farmacia_week->set_time_zone('UTC');
|
||||||
|
return $start_farmacia_week;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _build__db ($self) {
|
||||||
|
require BurguillosInfo::DB;
|
||||||
|
return BurguillosInfo::DB->connect( $self->_app );
|
||||||
|
}
|
||||||
|
1;
|
66
lib/BurguillosInfo/Farmacias.pm
Normal file
66
lib/BurguillosInfo/Farmacias.pm
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package BurguillosInfo::Farmacias;
|
||||||
|
|
||||||
|
use v5.36.0;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use utf8;
|
||||||
|
|
||||||
|
use Moo;
|
||||||
|
|
||||||
|
use Module::Pluggable
|
||||||
|
search_path => ['BurguillosInfo::Farmacias'],
|
||||||
|
instantiate => 'new',
|
||||||
|
on_require_error => sub ( $plugin, $error ) {
|
||||||
|
die $error;
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
my $array;
|
||||||
|
sub array($self) {
|
||||||
|
if (!defined $array) {
|
||||||
|
$self->_populate_farmacias;
|
||||||
|
}
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _populate_farmacias($self) {
|
||||||
|
$array = [];
|
||||||
|
@$array = $self->plugins();
|
||||||
|
for my $farmacia (@$array) {
|
||||||
|
$self->_check_farmacia_valid($farmacia);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $farmacias_by_id;
|
||||||
|
sub by_id($self, $target_id) {
|
||||||
|
if (!defined $farmacias_by_id) {
|
||||||
|
$self->_populate_farmacias_by_id;
|
||||||
|
}
|
||||||
|
if (!defined $target_id) {
|
||||||
|
die 'You must pass $target_id.';
|
||||||
|
}
|
||||||
|
my $farmacia = $farmacias_by_id->{$target_id};
|
||||||
|
if (!defined $farmacia) {
|
||||||
|
die "Farmacia $target_id not found.";
|
||||||
|
}
|
||||||
|
return $farmacia;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _populate_farmacias_by_id($self) {
|
||||||
|
$farmacias_by_id = {};
|
||||||
|
my $farmacias = $self->array;
|
||||||
|
for my $farmacia (@$farmacias) {
|
||||||
|
$farmacias_by_id->{$farmacia->id} = $farmacia;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _check_farmacia_valid($self, $farmacia) {
|
||||||
|
if ( !$farmacia->does('BurguillosInfo::Farmacia') ) {
|
||||||
|
die "$farmacia does not implement BurguillosInfo::Farmacia.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1;
|
27
lib/BurguillosInfo/Farmacias/CruzDeLaErmita.pm
Normal file
27
lib/BurguillosInfo/Farmacias/CruzDeLaErmita.pm
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package BurguillosInfo::Farmacias::CruzDeLaErmita;
|
||||||
|
|
||||||
|
use v5.36.0;
|
||||||
|
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use utf8;
|
||||||
|
|
||||||
|
use feature 'signatures';
|
||||||
|
|
||||||
|
use Moo;
|
||||||
|
use parent 'BurguillosInfo::Farmacia';
|
||||||
|
|
||||||
|
sub id {
|
||||||
|
return 'cruz_de_la_ermita';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub name {
|
||||||
|
return 'Farmacia Cruz de La Ermita';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub address {
|
||||||
|
return 'Avenida. Alcalde José Cuesta Godoy, Nº 21. (La calle aun es como Avenida Cruz de la Ermita si lo buscas en Google Maps.)';
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
24
lib/BurguillosInfo/Farmacias/Morera.pm
Normal file
24
lib/BurguillosInfo/Farmacias/Morera.pm
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package BurguillosInfo::Farmacias::Morera;
|
||||||
|
|
||||||
|
use v5.36.0;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use utf8;
|
||||||
|
|
||||||
|
use Moo;
|
||||||
|
|
||||||
|
sub id {
|
||||||
|
return 'morera';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub name {
|
||||||
|
return 'Farmacia Óptica Morera';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub address {
|
||||||
|
return 'Calle Virgen del Rosario número 13';
|
||||||
|
};
|
||||||
|
|
||||||
|
use parent 'BurguillosInfo::Farmacia';
|
||||||
|
1;
|
BIN
public/img/farmacia.webp
Normal file
BIN
public/img/farmacia.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 137 KiB |
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user