Adding Farmacia de Guardia.

This commit is contained in:
Sergiotarxz 2023-09-07 18:12:28 +02:00
parent 455afc62f5
commit af83dabf8c
13 changed files with 333 additions and 6 deletions

View File

@ -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,

View 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>

View File

@ -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

View File

@ -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');

View File

@ -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;

View File

@ -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);',
); );
} }

View 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;

View 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;

View 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;

View 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;

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

File diff suppressed because one or more lines are too long