our
$VERSION
= v0.14;
my
@musicbrainz_wikidata_relations
=
qw(P434 P435 P436 P966 P982 P1004 P1330 P1407 P4404 P5813 P6423 P8052)
;
my
$config_wikidata
= {
type
=>
'wikidata-identifier'
,
idmap
=> {
P213
=>
'isni'
,
P214
=>
'viaf-identifier'
,
P227
=>
'gnd-identifier'
,
P356
=>
'doi'
,
P402
=>
'osm-relation'
,
P409
=>
'libraries-australia-identifier'
,
P535
=>
'find-a-grave-identifier'
,
P648
=>
'open-library-identifier'
,
P1256
=>
'iconclass-identifier'
,
P1315
=>
'nla-trove-people-identifier'
,
P1566
=>
'geonames-identifier'
,
P1651
=>
'youtube-video-identifier'
,
P2041
=>
'ngv-artist-identifier'
,
P2949
=>
'wikitree-person-identifier'
,
P3916
=>
'unesco-thesaurus-identifier'
,
P4684
=>
'ngv-artwork-identifier'
,
P6735
=>
'tww-artist-identifier'
,
P6804
=>
'agsa-creator-identifier'
,
P7033
=>
'aev-identifier'
,
P7704
=>
'europeana-entity-identifier'
,
P8168
=>
'factgrid-identifier'
,
P8406
=>
'grove-art-online-identifier'
,
P9575
=>
'amc-artist-identifier'
,
P10086
=>
'a-p-and-p-artist-identifier'
,
P10689
=>
'osm-way'
,
P10787
=>
'factgrid-identifier'
,
P11693
=>
'osm-node'
,
(
map
{
$_
=>
'musicbrainz-identifier'
}
@musicbrainz_wikidata_relations
),
},
endpoint
=> {
},
uuid_relations
=> \
@musicbrainz_wikidata_relations
,
special_ids
=> [
{
property
=>
'P1711'
,
type
=>
'british-museum-term'
,
to_service
=>
sub
{(
$_
[0] =~ /^BIOG([1-9][0-9]+)$/)[0]},
from_service
=>
sub
{
sprintf
(
'BIOG%u'
,
$_
[0])},
},
],
attributes
=> [
(
map
{
my
$c
=
$_
; {
property
=>
$c
->[0],
from_service
=>
sub
{
return
(
$c
->[1] => {
'*'
=>
$_
[0]})},
}} (
[
P487
=>
'icon_text'
],
[
P1163
=>
'media_subtype'
],
)),
(
map
{
my
$c
=
$_
; {
property
=>
$c
->[0],
from_service
=>
sub
{_online_lookup__wikibase__from_service__datetime(
$c
->[1] =>
@_
)},
}} (
[
P569
=>
'date_of_birth'
],
[
P570
=>
'date_of_death'
],
)),
(
map
{
my
$c
=
$_
; {
property
=>
$c
->[0],
from_service
=>
sub
{
my
(
$value
,
$config
) =
@_
;
return
(
$c
->[1] => {
'*'
=> URI->new(
$value
)})
if
defined
$value
;
return
();
},
}} (
[
P856
=>
'website'
],
)),
(
map
{
my
$c
=
$_
; {
property
=>
$c
->[0],
from_service
=>
sub
{
my
(
$value
,
$config
) =
@_
;
return
(
$c
->[1] => {
'*'
=> URI->new(
$config
->{prefix} .
$value
->{id})})
if
defined
$value
->{id};
return
();
},
}} (
[
P21
=>
'sex_or_gender'
],
[
P376
=>
'space_object'
],
)),
(
map
{
my
$c
=
$_
; {
property
=>
$c
->[0],
list_value
=>
sub
{
my
(
$value
,
$config
) =
@_
;
return
(
$c
->[1] => [[URI->new(
$config
->{prefix} .
$value
->{id})]])
if
defined
$value
->{id};
return
();
},
}} (
[
P31
=>
'roles'
],
)),
{
property
=>
'P465'
,
from_service
=>
sub
{
my
(
$value
) =
@_
;
return
(
displaycolour
=> {
'*'
=> Data::URIID::Colour->new(
rgb
=>
sprintf
(
'#%s'
,
uc
(
$value
)))})
if
$value
=~ /^[0-9a-f-AF]{6}$/;
return
();
},
},
{
property
=>
'P625'
,
from_service
=> \
&_online_lookup__wikibase__from_service__coordinate
,
},
],
};
my
$config_factgrid
= {
type
=>
'factgrid-identifier'
,
idmap
=> {
P76
=>
'gnd-identifier'
,
P378
=>
'viaf-identifier'
,
P980
=>
'iconclass-identifier'
,
},
endpoint
=> {
},
attributes
=> [
(
map
{
my
$c
=
$_
; {
property
=>
$c
->[0],
from_service
=>
sub
{_online_lookup__wikibase__from_service__datetime(
$c
->[1] =>
@_
)},
}} (
[
P38
=>
'date_of_death'
],
[
P77
=>
'date_of_birth'
],
)),
(
map
{
my
$c
=
$_
; {
property
=>
$c
->[0],
from_service
=>
sub
{
my
(
$value
,
$config
) =
@_
;
return
(
$c
->[1] => {
'*'
=> URI->new(
$value
)})
if
defined
$value
;
return
();
},
}} (
[
P156
=>
'website'
],
)),
(
map
{
my
$c
=
$_
; {
property
=>
$c
->[0],
from_service
=>
sub
{
my
(
$value
,
$config
) =
@_
;
return
(
$c
->[1] => {
'*'
=> URI->new(
$config
->{prefix} .
$value
->{id})})
if
defined
$value
->{id};
return
();
},
}} (
[
P154
=>
'sex_or_gender'
],
[
P625
=>
'sex_or_gender'
],
)),
{
property
=>
'P48'
,
from_service
=> \
&_online_lookup__wikibase__from_service__coordinate
,
},
{
property
=>
'P696'
,
from_service
=>
sub
{
my
(
$value
) =
@_
;
return
(
displaycolour
=> {
'*'
=> Data::URIID::Colour->new(
rgb
=>
sprintf
(
'#%s'
,
uc
(
$value
)))})
if
$value
=~ /^[0-9a-f-AF]{6}$/;
return
();
},
},
],
};
my
@fellig_types
=
qw(fellig-identifier fellig-box-number uuid oid uri wikidata-identifier e621-post-identifier e621-pool-identifier wikimedia-commons-identifier british-museum-term musicbrainz-identifier gnd-identifier e621tagtype)
;
my
%attrmap_osm
= (
name
=>
'displayname'
,
description
=>
'description'
,
);
my
%attrmap_open_graph
= (
title
=>
'displayname'
,
description
=>
'description'
,
image
=>
'thumbnail'
,
);
my
%own_metadata
= (
service
=> {
'wikidata'
=> {
'displayname'
=> {
'*'
=>
'Wikidata'
},
},
'fellig'
=> {
'displayname'
=> {
'*'
=>
'Fellig.org'
},
},
'youtube'
=> {},
'youtube-nocookie'
=> {},
'dropbox'
=> {},
'0wx'
=> {},
'e621'
=> {},
'dnb'
=> {
'displayname'
=> {
'*'
=>
'Deutsche Nationalbibliothek'
},
},
'britishmuseum'
=> {
'displayname'
=> {
'*'
=>
'British Museum'
},
},
'musicbrainz'
=> {
'displayname'
=> {
'*'
=>
'MusicBrainz'
},
},
'wikimedia-commons'
=> {
'displayname'
=> {
'*'
=>
'Wikimedia Commons'
},
},
'wikipedia'
=> {
'displayname'
=> {
'*'
=>
'Wikipedia'
},
},
'noembed.com'
=> {},
'osm'
=> {
'displayname'
=> {
'*'
=>
'OpenStreetMap'
},
},
'overpass'
=> {},
'xkcd'
=> {},
'Data::URIID'
=> {},
'viaf'
=> {
'displayname'
=> {
'*'
=>
'Virtual International Authority File'
},
},
'europeana'
=> {},
'open-library'
=> {
'displayname'
=> {
'*'
=>
'Open Library'
},
},
'ngv'
=> {
'displayname'
=> {
'*'
=>
'National Gallery of Victoria'
},
},
'geonames'
=> {},
'find-a-grave'
=> {
'displayname'
=> {
'*'
=>
'Find a Grave'
},
},
'nla'
=> {
'displayname'
=> {
'*'
=>
'National Library of Australia'
},
},
'agsa'
=> {
'displayname'
=> {
'*'
=>
'Art Gallery of South Australia'
},
},
'amc'
=> {
'displayname'
=> {
'*'
=>
'Australian Music Centre'
},
},
'a-p-and-p'
=> {
'displayname'
=> {
'*'
=>
'Australian Prints + Printmaking'
},
},
'tww'
=> {
'displayname'
=> {
'*'
=>
'The Watercolour World'
},
},
'factgrid'
=> {
'displayname'
=> {
'*'
=>
'FactGrid'
},
},
'grove-art-online'
=> {
'displayname'
=> {
'*'
=>
'Grove Art Online'
},
},
'wikitree'
=> {
'displayname'
=> {
'*'
=>
'WikiTree'
},
},
'doi'
=> {
'displayname'
=> {
'*'
=>
'doi.org'
},
},
},
);
sub
_own_well_known {
state
$res
;
return
$res
if
defined
$res
;
my
%own_well_known
= (
'wikidata-identifier'
=> {
Q2
=> {
ids
=> {
'tagname'
=>
'Earth'
,
'aev-identifier'
=>
'scot/1917'
,
'factgrid-identifier'
=>
'Q176134'
,
'gnd-identifier'
=>
'1135962553'
,
'viaf-identifier'
=>
'6270149919445006650001'
,
'open-library-identifier'
=>
'earth_(planet)'
,
'unesco-thesaurus-identifier'
=>
'concept4083'
,
'geonames-identifier'
=>
'6295630'
,
},
attributes
=> {
'displayname'
=> {
'*'
=>
'Earth'
},
'description'
=> {
'*'
=>
'third planet from the sun in the solar system'
},
},
},
Q405
=> {
attributes
=> {
displayname
=> {
'*'
=>
'Moon'
}}},
Q6581072
=> {
attributes
=> {
displayname
=> {
'*'
=>
'female'
}}},
Q6581097
=> {
attributes
=> {
displayname
=> {
'*'
=>
'male'
}}}
},
'factgrid-identifier'
=> {
Q17
=> {
attributes
=> {
displayname
=> {
'*'
=>
'Female gender'
}}},
Q18
=> {
attributes
=> {
displayname
=> {
'*'
=>
'Male gender'
}}},
},
'media-subtype-identifier'
=> {
(
map
{
$_
=> {
attributes
=> {
displayname
=> {
'*'
=>
$_
},
},
ids
=> {
'uuid'
=> Data::URIID::Result->_media_subtype_to_uuid(
$_
),
'media-subtype-identifier'
=>
$_
,
'tagname'
=>
$_
,
},
}}
qw(
application/gzip
application/http
application/json
application/ld+json
application/octet-stream
application/ogg
application/pdf
application/vnd.debian.binary-package
application/vnd.oasis.opendocument.base
application/vnd.oasis.opendocument.chart
application/vnd.oasis.opendocument.chart-template
application/vnd.oasis.opendocument.formula
application/vnd.oasis.opendocument.formula-template
application/vnd.oasis.opendocument.graphics
application/vnd.oasis.opendocument.graphics-template
application/vnd.oasis.opendocument.image
application/vnd.oasis.opendocument.image-template
application/vnd.oasis.opendocument.presentation
application/vnd.oasis.opendocument.presentation-template
application/vnd.oasis.opendocument.spreadsheet
application/vnd.oasis.opendocument.spreadsheet-template
application/vnd.oasis.opendocument.text
application/vnd.oasis.opendocument.text-master
application/vnd.oasis.opendocument.text-master-template
application/vnd.oasis.opendocument.text-template
application/vnd.oasis.opendocument.text-web
application/xhtml+xml
application/xml
audio/flac
audio/matroska
audio/ogg
image/gif
image/jpeg
image/png
image/svg+xml
image/webp
message/http
text/html
text/plain
video/matroska
video/matroska-3d
video/ogg
video/webm
)
),
},
'language-tag-identifier'
=> {
en
=> {
attributes
=> {
displayname
=> {
'*'
=>
'English'
}}},
de
=> {
attributes
=> {
displayname
=> {
'*'
=>
'German'
}}},
},
'small-identifier'
=> {
map
{
$_
->{sid} => {
ids
=> {
uuid
=>
$_
->{uuid},
},
attributes
=> {
displayname
=> {
'*'
=>
$_
->{name}},
},
}} (
{
uuid
=>
'ddd60c5c-2934-404f-8f2d-fcb4da88b633'
,
sid
=> 1,
name
=>
'also-shares-identifier'
},
{
uuid
=>
'8be115d2-dc2f-4a98-91e1-a6e3075cbc31'
,
sid
=> 2,
name
=>
'uuid'
},
{
uuid
=>
'bfae7574-3dae-425d-89b1-9c087c140c23'
,
sid
=> 3,
name
=>
'tagname'
},
{
uuid
=>
'7f265548-81dc-4280-9550-1bd0aa4bf748'
,
sid
=> 4,
name
=>
'has-type'
},
{
uuid
=>
'a8d1637d-af19-49e9-9ef8-6bc1fbcf6439'
,
sid
=> 5,
name
=>
'uri'
},
{
uuid
=>
'd08dc905-bbf6-4183-b219-67723c3c8374'
,
sid
=> 6,
name
=>
'oid'
},
{
uuid
=>
'd0a4c6e2-ce2f-4d4c-b079-60065ac681f1'
,
sid
=> 8,
name
=>
'language-tag-identifier'
},
{
uuid
=>
'ce7aae1e-a210-4214-926a-0ebca56d77e3'
,
sid
=> 9,
name
=>
'wikidata-identifier'
},
{
uuid
=>
'923b43ae-a50e-4db3-8655-ed931d0dd6d4'
,
sid
=> 10,
name
=>
'specialises'
},
{
uuid
=>
'eacbf914-52cf-4192-a42c-8ecd27c85ee1'
,
sid
=> 11,
name
=>
'unicode-string'
},
{
uuid
=>
'928d02b0-7143-4ec9-b5ac-9554f02d3fb1'
,
sid
=> 12,
name
=>
'integer'
},
{
uuid
=>
'dea3782c-6bcb-4ce9-8a39-f8dab399d75d'
,
sid
=> 13,
name
=>
'unsigned-integer'
},
{
uuid
=>
'6ba648c2-3657-47c2-8541-9b73c3a9b2b4'
,
sid
=> 16,
name
=>
'default-context'
},
{
uuid
=>
'52a516d0-25d8-47c7-a6ba-80983e576c54'
,
sid
=> 17,
name
=>
'proto-file'
},
{
uuid
=>
'1cd4a6c6-0d7c-48d1-81e7-4e8d41fdb45d'
,
sid
=> 18,
name
=>
'final-file-size'
},
{
uuid
=>
'6085f87e-4797-4bb2-b23d-85ff7edc1da0'
,
sid
=> 19,
name
=>
'text-fragment'
},
{
uuid
=>
'4c9656eb-c130-42b7-9348-a1fee3f42050'
,
sid
=> 20,
name
=>
'also-list-contains-also'
},
{
uuid
=>
'298ef373-9731-491d-824d-b2836250e865'
,
sid
=> 21,
name
=>
'proto-message'
},
{
uuid
=>
'7be4d8c7-6a75-44cc-94f7-c87433307b26'
,
sid
=> 22,
name
=>
'proto-entity'
},
{
uuid
=>
'65bb36f2-b558-48af-8512-bca9150cca85'
,
sid
=> 23,
name
=>
'proxy-type'
},
{
uuid
=>
'a1c478b5-0a85-4b5b-96da-d250db14a67c'
,
sid
=> 24,
name
=>
'flagged-as'
},
{
uuid
=>
'59cfe520-ba32-48cc-b654-74f7a05779db'
,
sid
=> 25,
name
=>
'marked-as'
},
{
uuid
=>
'2bffc55d-7380-454e-bd53-c5acd525d692'
,
sid
=> 26,
name
=>
'roaraudio-error-number'
},
{
uuid
=>
'f87a38cb-fd13-4e15-866c-e49901adbec5'
,
sid
=> 27,
name
=>
'small-identifier'
},
{
uuid
=>
'd2750351-aed7-4ade-aa80-c32436cc6030'
,
sid
=> 28,
name
=>
'also-has-role'
},
{
uuid
=>
'448c50a8-c847-4bc7-856e-0db5fea8f23b'
,
sid
=> 32,
name
=>
'final-file-encoding'
},
{
uuid
=>
'79385945-0963-44aa-880a-bca4a42e9002'
,
sid
=> 33,
name
=>
'final-file-hash'
},
{
uuid
=>
'3fde5688-6e34-45e9-8f33-68f079b152c8'
,
sid
=> 34,
name
=>
'SEEK_SET'
},
{
uuid
=>
'bc598c52-642e-465b-b079-e9253cd6f190'
,
sid
=> 35,
name
=>
'SEEK_CUR'
},
{
uuid
=>
'06aff30f-70e8-48b4-8b20-9194d22fc460'
,
sid
=> 36,
name
=>
'SEEK_END'
},
{
uuid
=>
'59a5691a-6a19-4051-bc26-8db82c019df3'
,
sid
=> 37,
name
=>
'inode'
},
{
uuid
=>
'ae8ec1de-38ec-4c58-bbd7-7ff43e1100fc'
,
sid
=> 38,
name
=>
'in-reply-to'
},
{
uuid
=>
'8a31868b-0a26-42e0-ac54-819a9ed9dcab'
,
sid
=> 39,
name
=>
'in-response-to'
},
{
uuid
=>
'ffa893a2-9a0e-4013-96b4-307e2bca15b9'
,
sid
=> 40,
name
=>
'has-message-body'
},
{
uuid
=>
'b72508ba-7fb9-42ae-b4cf-b850b53a16c2'
,
sid
=> 41,
name
=>
'account'
},
{
uuid
=>
'4e855294-4b4f-443e-b67b-8cb9d733a889'
,
sid
=> 43,
name
=>
'backwards'
},
{
uuid
=>
'6ad2c921-7a3e-4859-ae02-98e42522e2f8'
,
sid
=> 44,
name
=>
'forwards'
},
{
uuid
=>
'dd8e13d3-4b0f-5698-9afa-acf037584b20'
,
sid
=> 48,
name
=>
'zero'
},
{
uuid
=>
'bd27669b-201e-51ed-9eb8-774ba7fef7ad'
,
sid
=> 49,
name
=>
'one'
},
{
uuid
=>
'73415b5a-31fb-5b5a-bb82-8ea5eb3b12f7'
,
sid
=> 50,
name
=>
'two'
},
{
uuid
=>
'e425be57-58cb-43fb-ba85-c1a55a6a2ebd'
,
sid
=> 52,
name
=>
'ancestor-of'
},
{
uuid
=>
'cdee05f4-91ec-4809-a157-8c58dcb23715'
,
sid
=> 53,
name
=>
'descendant-of'
},
{
uuid
=>
'26bda7b1-4069-4003-925c-2dbf47833a01'
,
sid
=> 54,
name
=>
'sibling-of'
},
{
uuid
=>
'a75f9010-9db3-4d78-bd78-0dd528d6b55d'
,
sid
=> 55,
name
=>
'see-also'
},
{
uuid
=>
'd1963bfc-0f79-4b1a-a95a-b05c07a63c2a'
,
sid
=> 56,
name
=>
'also-at'
},
{
uuid
=>
'c6e83600-fd96-4b71-b216-21f0c4d73ca6'
,
sid
=> 57,
name
=>
'also-shares-colour'
},
{
uuid
=>
'a942ba41-20e6-475e-a2c1-ce891f4ac920'
,
sid
=> 58,
name
=>
'also-identifies-as'
},
{
uuid
=>
'ac14b422-e7eb-4e5b-bccd-ad5a65aeab96'
,
sid
=> 59,
name
=>
'also-is-identified-as'
},
{
uuid
=>
'3c2c155f-a4a0-49f3-bdaf-7f61d25c6b8c'
,
sid
=> 60,
name
=>
'Earth'
},
{
uuid
=>
'fade296d-c34f-4ded-abd5-d9adaf37c284'
,
sid
=> 61,
name
=>
'black'
},
{
uuid
=>
'1a2c23fa-2321-47ce-bf4f-5f08934502de'
,
sid
=> 62,
name
=>
'white'
},
{
uuid
=>
'f9bb5cd8-d8e6-4f29-805f-cc6f2b74802d'
,
sid
=> 63,
name
=>
'grey'
},
{
uuid
=>
'dd708015-0fdd-4543-9751-7da42d19bc6a'
,
sid
=> 64,
name
=>
'Sun'
},
{
uuid
=>
'23026974-b92f-4820-80f6-c12f4dd22fca'
,
sid
=> 65,
name
=>
'Luna'
},
{
uuid
=>
'd642eff3-bee6-5d09-aea9-7c47b181dd83'
,
sid
=> 75,
name
=>
'male'
},
{
uuid
=>
'db9b0db1-a451-59e8-aa3b-9994e683ded3'
,
sid
=> 76,
name
=>
'female'
},
{
uuid
=>
'f6249973-59a9-47e2-8314-f7cf9a5f77bf'
,
sid
=> 77,
name
=>
'person'
},
{
uuid
=>
'5501e545-f39a-4d62-9f65-792af6b0ccba'
,
sid
=> 78,
name
=>
'body'
},
{
uuid
=>
'a331f2c5-20e5-4aa2-b277-8e63fd03438d'
,
sid
=> 79,
name
=>
'character'
},
{
uuid
=>
'838eede5-3f93-46a9-8e10-75165d10caa1'
,
sid
=> 80,
name
=>
'cat'
},
{
uuid
=>
'252314f9-1467-48bf-80fd-f8b74036189f'
,
sid
=> 81,
name
=>
'dog'
},
{
uuid
=>
'571fe2aa-95f6-4b16-a8d2-1ff4f78bdad1'
,
sid
=> 82,
name
=>
'lion'
},
{
uuid
=>
'36297a27-0673-44ad-b2d8-0e4e97a9022d'
,
sid
=> 83,
name
=>
'tiger'
},
{
uuid
=>
'5d006ca0-c27b-4529-b051-ac39c784d5ee'
,
sid
=> 84,
name
=>
'fox'
},
{
uuid
=>
'914b3a09-4e01-4afc-a065-513c199b6c24'
,
sid
=> 85,
name
=>
'squirrel'
},
{
uuid
=>
'95f1b56e-c576-4f32-ac9b-bfdd397c36a6'
,
sid
=> 86,
name
=>
'wolf'
},
{
uuid
=>
'dcf8f4f0-c15e-44bd-ad76-0d483079db16'
,
sid
=> 87,
name
=>
'human'
},
{
uuid
=>
'f901e5e0-e217-41c8-b752-f7287af6e6c3'
,
sid
=> 89,
name
=>
'mammal'
},
{
uuid
=>
'7ed4160e-06d6-44a2-afe8-457e2228304d'
,
sid
=> 90,
name
=>
'vertebrate'
},
{
uuid
=>
'0510390c-9604-4362-b603-ea09e48de7b7'
,
sid
=> 91,
name
=>
'animal'
},
{
uuid
=>
'bccdaf71-0c82-422e-af44-bb8396bf90ed'
,
sid
=> 92,
name
=>
'plant'
},
{
uuid
=>
'a0b8122e-d11b-4b78-a266-0bb90d1c1cbe'
,
sid
=> 93,
name
=>
'fungus'
},
{
uuid
=>
'3e92ac2d-f8fe-48bf-acd7-8505d23d07ab'
,
sid
=> 94,
name
=>
'organism'
},
{
uuid
=>
'115c1bcf-02cd-4a57-bd02-1d9f1ea8dd01'
,
sid
=> 95,
name
=>
'any-taxon'
},
{
uuid
=>
'd2526d8b-25fa-4584-806b-67277c01c0db'
,
sid
=> 96,
name
=>
'inode-number'
},
{
uuid
=>
'cd5bfb11-620b-4cce-92bd-85b7d010f070'
,
sid
=> 97,
name
=>
'also-on-filesystem'
},
{
uuid
=>
'63c1da19-0dd6-4181-b3fa-742b9ceb2903'
,
sid
=> 98,
name
=>
'filesystem'
},
{
uuid
=>
'5ecb4562-dad7-431d-94a6-d301dcea8d37'
,
sid
=> 99,
name
=>
'parent'
},
{
uuid
=>
'1a9215b2-ad06-4f4f-a1e7-4cbb908f7c7c'
,
sid
=> 100,
name
=>
'child'
},
{
uuid
=>
'a7cfbcb0-45e2-46b9-8f60-646ab2c18b0b'
,
sid
=> 101,
name
=>
'displaycolour'
},
{
uuid
=>
'd926eb95-6984-415f-8892-233c13491931'
,
sid
=> 103,
name
=>
'tag-links'
},
{
uuid
=>
'2c07ddc1-bdb8-435a-9614-4e6782a5101f'
,
sid
=> 104,
name
=>
'tag-linked-by'
},
{
uuid
=>
'4efce01d-411e-5e9c-9ed9-640ecde31d1d'
,
sid
=> 105,
name
=>
'parallel'
},
{
uuid
=>
'9aad6c99-67cd-45fd-a8a6-760d863ce9b5'
,
sid
=> 106,
name
=>
'also-where'
},
{
uuid
=>
'8efbc13b-47e5-4d92-a960-bd9a2efa9ccb'
,
sid
=> 107,
name
=>
'generated-by'
},
{
uuid
=>
'83e3acbb-eb8d-4dfb-8f2f-ae81cc436d4b'
,
sid
=> 109,
name
=>
'batch'
},
{
uuid
=>
'b17f36c6-c397-4e84-bd32-1eccb3f00671'
,
sid
=> 110,
name
=>
'set'
},
{
uuid
=>
'aa9d311a-89b7-44cc-a356-c3fc93dfa951'
,
sid
=> 111,
name
=>
'category'
},
{
uuid
=>
'2c7e15ed-aa2f-4e2f-9a1d-64df0c85875a'
,
sid
=> 112,
name
=>
'chat-0-word-identifier'
},
{
uuid
=>
'c9ec3bea-558e-4992-9b76-91f128b6cf29'
,
sid
=> 119,
name
=>
'red'
},
{
uuid
=>
'c0e957d0-b5cf-4e53-8e8a-ff0f5f2f3f03'
,
sid
=> 120,
name
=>
'green'
},
{
uuid
=>
'3dcef9a3-2ecc-482d-a98b-afffbc2f64b9'
,
sid
=> 121,
name
=>
'blue'
},
{
uuid
=>
'abcbf48d-c302-4be1-8c5c-a8de4471bcbb'
,
sid
=> 122,
name
=>
'cyan'
},
{
uuid
=>
'a30d070d-9909-40d4-a33a-474c89e5cd45'
,
sid
=> 123,
name
=>
'magenta'
},
{
uuid
=>
'2892c143-2ae7-48f1-95f4-279e059e7fc3'
,
sid
=> 124,
name
=>
'yellow'
},
{
uuid
=>
'5c41829f-5062-4868-9c31-2ec98414c53d'
,
sid
=> 125,
name
=>
'orange'
},
{
uuid
=>
'c90acb33-b8ea-4f55-bd86-beb7fa5cf80a'
,
sid
=> 126,
name
=>
'savannah'
},
{
uuid
=>
'caf11e36-d401-4521-8f10-f6b36125415c'
,
sid
=> 132,
name
=>
'icon'
},
{
uuid
=>
'e7330249-53b8-4dab-aa43-b5bfa331a8e5'
,
sid
=> 133,
name
=>
'thumbnail'
},
{
uuid
=>
'2ec4a6b0-e6bf-40cd-96a2-490cbc8d6c4b'
,
sid
=> 134,
name
=>
'empty-set'
},
{
uuid
=>
'be6d8e00-a6c1-5c44-8ffc-f7393e14aa23'
,
sid
=> 144,
name
=>
'three'
},
{
uuid
=>
'79422b2c-b6f6-547f-949f-0cba44fa69b7'
,
sid
=> 145,
name
=>
'four'
},
{
uuid
=>
'7cb67873-33bc-4a93-b53f-072ce96c6f1a'
,
sid
=> 159,
name
=>
'hrair'
},
{
uuid
=>
'82d529be-0f00-4b4f-a43f-4a22de5f5312'
,
sid
=> 160,
name
=>
'gtin'
},
{
uuid
=>
'e8c156be-4fe7-4b13-b4fa-e207213caef8'
,
sid
=> 161,
name
=>
'subject-type'
},
{
uuid
=>
'c44ee482-0fb7-421b-9aad-a6c8f099a4b6'
,
sid
=> 176,
name
=>
'Universe'
},
{
uuid
=>
'0ac40a25-d20f-42ed-ae1c-64e62a56d673'
,
sid
=> 177,
name
=>
'Observable universe'
},
{
uuid
=>
'8a1cb2d6-df2f-46db-89c3-a75168adebf6'
,
sid
=> 189,
name
=>
'generator'
},
{
uuid
=>
'3c9f40b4-2b98-44ce-b4dc-97649eb528ae'
,
sid
=> 190,
name
=>
'using-namespace'
},
{
uuid
=>
'bc2d2e7c-8aa4-420e-ac07-59c422034de9'
,
sid
=> 191,
name
=>
'for-type'
},
{
uuid
=>
'5cbdbe1c-e8b6-4cac-b274-b066a7f86b28'
,
sid
=> 192,
name
=>
'left'
},
{
uuid
=>
'3b1858a9-996b-4831-b600-eb55ab7bb0d1'
,
sid
=> 193,
name
=>
'right'
},
{
uuid
=>
'f158e457-9a75-42ac-b864-914b34e813c7'
,
sid
=> 194,
name
=>
'up'
},
{
uuid
=>
'4c834505-8e77-4da6-b725-e11b6572d979'
,
sid
=> 195,
name
=>
'down'
},
{
uuid
=>
'fd324dee-4bc7-4716-bf0c-6d50a69961b7'
,
sid
=> 208,
name
=>
'north'
},
{
uuid
=>
'8685e1d8-f313-403a-9f4d-48fce22f9312'
,
sid
=> 209,
name
=>
'east'
},
{
uuid
=>
'c65c5baf-630e-4a28-ace5-1082b032dd07'
,
sid
=> 210,
name
=>
'south'
},
{
uuid
=>
'7ed25dc4-5afc-4b39-8446-4df7748040a4'
,
sid
=> 211,
name
=>
'west'
},
{
uuid
=>
'7ce365d8-71d2-4bd6-95c9-888a8f1d834c'
,
sid
=> 212,
name
=>
'northeast'
},
{
uuid
=>
'39be7db6-1dc7-41c3-acd2-de19ad17a97f'
,
sid
=> 213,
name
=>
'northwest'
},
{
uuid
=>
'33233365-20ec-4073-9962-0cb4b1b1e48d'
,
sid
=> 214,
name
=>
'southeast'
},
{
uuid
=>
'b47ecfde-02b1-4790-85dd-c2e848c89d2e'
,
sid
=> 215,
name
=>
'southwest'
},
),
},
'uuid'
=> {
map
{
$_
->{uuid} => {
attributes
=> {
displayname
=> {
'*'
=>
$_
->{name}},
},
}} (
{
uuid
=>
'878aac4c-581b-4257-998c-19a9c4003d22'
,
name
=>
'colour'
},
),
},
);
foreach
my
$id
(
keys
%{
$own_well_known
{
'wikidata-identifier'
}}) {
my
$uuid
= create_uuid_as_string(UUID_SHA1,
'9e10aca7-4a99-43ac-9368-6cbfa43636df'
,
lc
$id
);
$own_well_known
{uuid}{
$uuid
} =
$own_well_known
{
'wikidata-identifier'
}{
$id
};
}
my
@colours
= (
[
black
=>
'fade296d-c34f-4ded-abd5-d9adaf37c284'
=>
'#000000'
],
[
white
=>
'1a2c23fa-2321-47ce-bf4f-5f08934502de'
=>
'#ffffff'
],
[
red
=>
'c9ec3bea-558e-4992-9b76-91f128b6cf29'
=>
'#ff0000'
],
[
green
=>
'c0e957d0-b5cf-4e53-8e8a-ff0f5f2f3f03'
=>
'#008000'
],
[
blue
=>
'3dcef9a3-2ecc-482d-a98b-afffbc2f64b9'
=>
'#0000ff'
],
[
cyan
=>
'abcbf48d-c302-4be1-8c5c-a8de4471bcbb'
=>
'#00ffff'
],
[
magenta
=>
'a30d070d-9909-40d4-a33a-474c89e5cd45'
=>
'#ff00ff'
],
[
yellow
=>
'2892c143-2ae7-48f1-95f4-279e059e7fc3'
=>
'#ffff00'
],
[
grey
=>
'f9bb5cd8-d8e6-4f29-805f-cc6f2b74802d'
=>
'#808080'
],
[
orange
=>
'5c41829f-5062-4868-9c31-2ec98414c53d'
=>
'#ff8000'
],
[
savannah
=>
'c90acb33-b8ea-4f55-bd86-beb7fa5cf80a'
=>
'#decc9c'
],
[
black
=>
'32f5e924-0ddb-4427-ad81-2d099b590c68'
=>
'#000000'
],
[
maroon
=>
'2aeedebd-2814-41b3-9cfd-f992e9a60827'
=>
'#800000'
],
[
green
=>
'd045d86c-3437-4b42-aa77-2d7ac6ff1656'
=>
'#008000'
],
[
olive
=>
'a64b447b-3eb3-4a71-92fe-f4399e845892'
=>
'#808000'
],
[
navy
=>
'f8ace5ee-45a9-4e46-8324-095b6ab452b5'
=>
'#000080'
],
[
purple
=>
'7cd1228f-b55b-4b86-a057-f620e7934f7f'
=>
'#800080'
],
[
teal
=>
'c7d4cc0e-dd3b-465c-b1ed-6fea3d424b9f'
=>
'#008080'
],
[
gray
=>
'aa82b49e-12c2-41a4-9fd8-800957be9161'
=>
'#808080'
],
[
silver
=>
'cdb01cbf-0eca-4aad-b732-caf55abc7566'
=>
'#C0C0C0'
],
[
red
=>
'6d62509a-aac5-412b-953b-e002867090ef'
=>
'#FF0000'
],
[
lime
=>
'18b0ad77-95a1-4ddc-8a3e-52fb1fca2ead'
=>
'#00FF00'
],
[
yellow
=>
'b85fca40-ab8e-4ab3-b582-43cb0979b994'
=>
'#FFFF00'
],
[
blue
=>
'7f2e2d6a-ec70-417b-8418-a5d67c05b7e0'
=>
'#0000FF'
],
[
fuchsia
=>
'465087e0-a8d0-4a42-8f05-a1aea0d53385'
=>
'#FF00FF'
],
[
aqua
=>
'4feff8a2-dbe4-447b-b052-db333b9ebee3'
=>
'#00FFFF'
],
[
white
=>
'a671d5f4-5a1d-498d-b3ec-52b92f15218e'
=>
'#FFFFFF'
],
);
my
$colour_roles
= {
'*'
=> [[URI->new(
'urn:uuid:878aac4c-581b-4257-998c-19a9c4003d22'
)]]};
my
@displaycolours
;
foreach
my
$list
(\
@colours
, \
@displaycolours
) {
foreach
my
$colour
(@{
$list
}) {
my
(
$name
,
$uuid
,
$displaycolour
) = @{
$colour
};
my
$e
= (
$own_well_known
{uuid}{
$uuid
} //= {})->{attributes} //= {};
my
$colour_object
= Data::URIID::Colour->new(
rgb
=>
$displaycolour
,
register
=> 1);
if
(
defined
$name
) {
$e
->{displayname} //= {};
$e
->{displayname}{
'*'
} //=
$name
;
}
$e
->{displaycolour} //= {};
$e
->{displaycolour}{
'*'
} //=
$colour_object
;
$e
->{roles} =
$colour_roles
;
if
(
$list
!= \
@displaycolours
) {
push
(
@displaycolours
, [
undef
,
$colour_object
->ise,
$displaycolour
]);
}
}
}
foreach
my
$type
(
keys
%own_well_known
) {
foreach
my
$entry
(
values
%{
$own_well_known
{
$type
}}) {
my
$dpca
=
$entry
->{attributes}{displaycolour} //
next
;
my
$displaycolour
=
$dpca
->{
'*'
} //
next
;
my
$e
= (
$own_well_known
{uuid}{
$displaycolour
->ise} //= {})->{attributes} //= {};
$e
->{displaycolour} //= {};
$e
->{displaycolour}{
'*'
} //=
$displaycolour
;
}
}
foreach
my
$language
(
keys
%{
$own_well_known
{
'language-tag-identifier'
}}) {
my
$uuid
= create_uuid_as_string(UUID_SHA1,
'47dd950c-9089-4956-87c1-54c122533219'
,
lc
$language
);
$own_well_known
{uuid}{
$uuid
} =
$own_well_known
{
'language-tag-identifier'
}{
$language
};
}
foreach
my
$id_type_outer
(
keys
%own_well_known
) {
foreach
my
$src_id
(
keys
%{
$own_well_known
{
$id_type_outer
}}) {
my
$src
=
$own_well_known
{
$id_type_outer
}{
$src_id
};
my
$s_ids
=
$src
->{ids} //= {};
my
$s_attrs
=
$src
->{attributes} //= {};
$s_ids
->{
$id_type_outer
} =
$src_id
;
foreach
my
$id_type_inner
(
keys
%{
$s_ids
}) {
my
$dst
= (
$own_well_known
{
$id_type_inner
} //= {})->{
$s_ids
->{
$id_type_inner
}} //= {};
if
(
$src
!=
$dst
) {
my
$d_ids
=
$dst
->{ids} //= {};
my
$d_attrs
=
$dst
->{attributes} //= {};
$s_ids
->{
$_
} //=
$d_ids
->{
$_
}
foreach
keys
%{
$d_ids
};
$s_attrs
->{
$_
} //=
$d_attrs
->{
$_
}
foreach
keys
%{
$d_attrs
};
$own_well_known
{
$id_type_inner
}{
$s_ids
->{
$id_type_inner
}} =
$src
;
}
}
}
}
return
$res
= \
%own_well_known
;
}
sub
new {
my
(
$pkg
,
%opts
) =
@_
;
weaken(
$opts
{extractor});
return
bless
\
%opts
,
$pkg
;
}
sub
_is_online {
my
(
$self
) =
@_
;
return
$self
->online &&
$self
->extractor->online;
}
sub
_online_lookup {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$func
;
return
undef
unless
$self
->_is_online;
$func
=
$self
->can(
sprintf
(
'_online_lookup__%s'
,
$self
->name =~
tr
/\.:\-/_/r));
return
undef
unless
$func
;
return
$self
->
$func
(
$result
,
%opts
);
}
sub
_offline_lookup {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$func
;
$func
=
$self
->can(
sprintf
(
'_offline_lookup__%s'
,
$self
->name =~
tr
/\.:\-/_/r));
return
undef
unless
$func
;
return
$self
->
$func
(
$result
,
%opts
);
}
sub
name {
my
(
$self
) =
@_
;
return
$self
->{name} //=
$self
->extractor->ise_to_name(
service
=>
$self
->ise);
}
sub
online {
my
(
$self
,
$new_value
) =
@_
;
if
(
scalar
(
@_
) == 2) {
$self
->{online} = !!
$new_value
;
}
return
$self
->{online};
}
sub
setting {
my
(
$self
,
$setting
,
$new_value
) =
@_
;
$self
->{setting} //= {};
if
(
scalar
(
@_
) == 3) {
$self
->{setting}{
$setting
} =
$new_value
;
}
return
$self
->{setting}{
$setting
};
}
sub
_extra_lookup_services {
return
{
'wikidata'
=> [
values
(%{
$config_wikidata
->{idmap}}),
qw(wikidata-identifier british-museum-term uuid)
],
'wikimedia-commons'
=> [
qw(wikimedia-commons-identifier)
],
'fellig'
=> \
@fellig_types
,
'noembed.com'
=> [
qw(youtube-video-identifier)
],
'osm'
=> [
qw(osm-node osm-way osm-relation)
],
'overpass'
=> [
qw(wikidata-identifier)
],
'Data::URIID'
=> [
qw(uuid oid uri)
,
keys
%{_own_well_known()},
],
'Data::Identifier'
=> [
qw(uuid oid uri)
,
qw(e621-post-identifier e621-pool-identifier)
,
keys
%{_own_well_known()},
],
'factgrid'
=> [
values
(%{
$config_factgrid
->{idmap}}),
qw(factgrid-identifier)
],
'doi'
=> [
qw(doi)
],
'iconclass'
=> [
'iconclass-identifier'
],
'xkcd'
=> [
'xkcd-num'
],
'e621'
=> [
'e621-post-identifier'
,
'e621-pool-identifier'
],
'furaffinity'
=> [
'furaffinity-post-identifier'
],
'imgur'
=> [
'imgur-post-identifier'
],
'notalwaysright'
=> [
'notalwaysright-post-identifier'
],
'ruthede'
=> [
'ruthede-comic-post-identifier'
],
}
}
sub
_extra_lookup_services_digests {
return
{
'e621'
=> [
'md-5-128'
],
};
}
sub
_get_html {
my
(
$self
,
$url
,
%opts
) =
@_
;
if
(
$self
->setting(
'network_deny'
)) {
return
undef
;
}
if
(
$HAVE_HTML_TreeBuilder_XPath
) {
my
Data::URIID
$extractor
=
$self
->extractor;
if
(
defined
(
my
$query
=
$opts
{query})) {
$url
=
ref
(
$url
) ?
$url
->clone : URI->new(
$url
);
$url
->query_form(
$url
->query_form, %{
$query
});
}
return
eval
{
my
$msg
=
$extractor
->_ua->get(
$url
,
'Accept'
=>
'text/html'
);
return
undef
unless
$msg
->is_success;
my
$val
=
$msg
->decoded_content(
ref
=> 1,
charset
=>
'none'
);
my
$r
= HTML::TreeBuilder::XPath->new;
$r
->parse(decode(
$msg
->content_charset,
$$val
));
$r
->
eof
;
$r
;
};
}
else
{
return
undef
;
}
}
sub
_get_json {
my
(
$self
,
$url
,
%opts
) =
@_
;
my
Data::URIID
$extractor
=
$self
->extractor;
if
(
$self
->setting(
'network_deny'
) ) {
return
undef
;
}
if
(
defined
(
my
$local_override
=
$opts
{local_override})) {
if
(
defined
(
my
$local_override_dir
=
$self
->setting(
'local_override_dir'
))) {
my
(
$path
,
@args
) = @{
$local_override
};
if
(all {
defined
}
@args
) {
my
$data
;
$path
=~ s/
%s
/uri_escape_utf8(
shift
(
@args
))/ge;
$path
=
$local_override_dir
.
'/'
.
$path
;
$data
=
$self
->_get_json_file(
$path
);
return
$data
if
defined
$data
;
}
}
}
if
(
defined
(
my
$query
=
$opts
{query})) {
$url
=
ref
(
$url
) ?
$url
->clone : URI->new(
$url
);
$url
->query_form(
$url
->query_form, %{
$query
});
}
return
eval
{
my
$msg
=
$extractor
->_ua->get(
$url
,
'Accept'
=>
'application/json'
);
return
undef
unless
$msg
->is_success;
my
$val
=
$msg
->decoded_content(
ref
=> 1,
charset
=>
'none'
);
from_json(decode(
$msg
->content_charset,
$$val
));
};
}
sub
_get_json_file {
my
(
$self
,
$filename
) =
@_
;
my
$fh
=
eval
{
open
(
my
$fh
,
'<'
,
$filename
) or
die
$!;
$fh
; } //
eval
{
open
(
my
$fh
,
'<:gzip'
,
$filename
.
'.gz'
) or
die
$!;
$fh
; };
return
undef
unless
$fh
;
return
eval
{
local
$/ =
undef
;
from_json(
scalar
<
$fh
>);
};
}
sub
_load_open_graph {
my
(
$self
,
$res
,
$html
,
$keys
,
$filters
) =
@_
;
my
$attr
=
$res
->{attributes} //= {};
my
%raw
=
map
{
$_
->attr(
'property'
) =>
$_
->attr(
'content'
)}
$html
->findnodes(
'/html/head/meta[@property]'
);
$filters
//= {};
foreach
my
$key
(@{
$keys
}) {
my
$attrname
=
$attrmap_open_graph
{
$key
} // croak
'BUG: Unknown key name: '
.
$key
;
my
$filter
=
$filters
->{
$key
};
if
(
defined
(
my
$value
=
$raw
{
'og:'
.
$key
})) {
if
(
length
(
$value
)) {
if
(
defined
$filter
) {
next
unless
$value
=~
$filter
;
}
$attr
->{
$attrname
} //= {};
$attr
->{
$attrname
}{
'*'
} //=
$value
;
}
}
}
}
sub
_get_uriid_decompiled_types_json {
my
(
$self
) =
@_
;
state
$json
= {
types
=> {
'oid'
=> {
alias_for
=>
'd08dc905-bbf6-4183-b219-67723c3c8374'
},
'uri'
=> {
alias_for
=>
'a8d1637d-af19-49e9-9ef8-6bc1fbcf6439'
},
'uuid'
=> {
alias_for
=>
'8be115d2-dc2f-4a98-91e1-a6e3075cbc31'
},
'wikidata-identifier'
=> {
alias_for
=>
'ce7aae1e-a210-4214-926a-0ebca56d77e3'
},
'gtin'
=> {
alias_for
=>
'82d529be-0f00-4b4f-a43f-4a22de5f5312'
},
'sid'
=> {
alias_for
=>
'f87a38cb-fd13-4e15-866c-e49901adbec5'
},
}};
return
state
$decompiled
=
do
{{
forward
=>
$json
,
backward
=> {
map
{
$json
->{types}{
$_
}{alias_for} =>
$_
}
grep
{
defined
$json
->{types}{
$_
}{alias_for}}
keys
%{
$json
->{types}}},
}};
}
sub
_offline_lookup__Data__URIID {
my
(
$self
,
$result
) =
@_
;
my
Data::URIID
$extractor
=
$self
->extractor;
my
$ise_order
=
$result
->{primary}{ise_order} // [
qw(uuid oid uri)
];
state
$own_well_known
= _own_well_known();
my
%attr
;
my
%ids
;
my
@found
;
outer:
foreach
my
$ise_type
(@{
$ise_order
}) {
my
$ise
=
eval
{
$result
->id(
$ise_type
)} //
next
;
foreach
my
$type
(
qw(service type action)
) {
my
$name
=
eval
{
$extractor
->ise_to_name(
$type
=>
$ise
) } //
next
;
my
$displayname
=
$attr
{displayname} //= {};
$displayname
->{
'*'
} //=
$name
;
push
(
@found
, {
attributes
=>
$own_metadata
{
$type
}{
$name
}});
last
outer;
}
}
foreach
my
$id_type
(
keys
%{
$own_well_known
}) {
my
$id
=
eval
{
$result
->id(
$id_type
,
_no_convert
=> 1)};
if
(
defined
$id
) {
if
(
defined
(
my
$entry
=
$own_well_known
->{
$id_type
}{
$id
})) {
push
(
@found
,
$entry
);
}
}
}
foreach
my
$found
(
@found
) {
my
$attributes
=
$found
->{attributes};
my
$ids
=
$found
->{ids};
foreach
my
$attr
(
keys
%{
$attributes
//{}}) {
$attr
{
$attr
} //= {};
foreach
my
$key
(
keys
%{
$attributes
->{
$attr
}}) {
$attr
{
$attr
}{
$key
} =
$attributes
->{
$attr
}{
$key
};
}
}
foreach
my
$id_type
(
keys
%{
$ids
//{}}) {
$ids
{
$id_type
} //=
$ids
->{
$id_type
};
}
}
{
my
%res
;
$res
{id} = \
%ids
if
scalar
keys
%ids
;
$res
{attributes} = \
%attr
if
scalar
keys
%attr
;
return
\
%res
;
}
}
sub
_offline_lookup__Data__Identifier {
my
(
$self
,
$result
) =
@_
;
my
$ise_order
=
$result
->{primary}{ise_order} // [
qw(uuid oid uri)
];
my
%attr
;
my
%ids
;
eval
{
$result
->id(
'uri'
) };
foreach
my
$id
(
map
{
eval
{
$result
->id(
$_
,
as
=>
'Data::Identifier'
,
_no_convert
=> 1)}
} (
$result
->{primary}{type},
@{
$ise_order
},
)) {
next
unless
defined
$id
;
if
(
defined
(
my
$displayname
=
$id
->displayname(
default
=>
undef
,
no_defaults
=> 1))) {
$attr
{displayname} //= {
'*'
=>
$displayname
};
}
foreach
my
$type
(
qw(uuid oid uri sid)
) {
my
$func
=
$id
->can(
$type
);
if
(
defined
(
my
$value
=
$id
->
$func
(
default
=>
undef
))) {
$ids
{
$type
eq
'sid'
?
'small-identifier'
:
$type
} //=
$value
;
}
}
}
{
my
%res
;
$res
{id} = \
%ids
if
scalar
keys
%ids
;
$res
{attributes} = \
%attr
if
scalar
keys
%attr
;
return
\
%res
;
}
}
sub
_online_lookup__wikidata {
my
(
$self
,
$result
) =
@_
;
return
_online_lookup__wikibase(
$self
,
$result
,
$config_wikidata
);
}
sub
_online_lookup__factgrid {
my
(
$self
,
$result
) =
@_
;
return
_online_lookup__wikibase(
$self
,
$result
,
$config_factgrid
);
}
sub
_online_lookup__wikibase {
my
(
$self
,
$result
,
$config
) =
@_
;
my
$id
=
eval
{
$result
->id(
$config
->{type})};
unless
(
defined
$id
) {
$id
=
$self
->_online_lookup__wikibase__stage_0(
$result
,
$config
);
}
if
(
defined
$id
) {
return
$self
->_online_lookup__wikibase__stage_1(
$result
,
$id
,
$config
);
}
return
undef
;
}
sub
_online_lookup__wikibase__stage_0 {
my
(
$self
,
$result
,
$config
) =
@_
;
my
@ids
;
foreach
my
$property
(
keys
%{
$config
->{idmap}}) {
my
$id
=
eval
{
$result
->id(
$config
->{idmap}{
$property
})};
if
(
defined
$id
) {
if
(
$id
!~ /['"]/) {
push
(
@ids
,
sprintf
(
'?item wdt:%s "%s"'
,
$property
,
$id
));
}
}
}
foreach
my
$special
(@{
$config
->{special_ids}}) {
my
$id
=
eval
{
$result
->id(
$special
->{type})};
if
(
defined
$id
) {
push
(
@ids
,
sprintf
(
'?item wdt:%s "%s"'
,
$special
->{property},
$special
->{to_service}->(
$id
)));
}
}
{
my
$id
=
eval
{
$result
->id(
'uuid'
)};
if
(
defined
$id
) {
foreach
my
$property
(@{
$config
->{uuid_relations}}) {
push
(
@ids
,
sprintf
(
'?item wdt:%s "%s"'
,
$property
,
$id
));
}
}
}
return
undef
unless
scalar
@ids
;
{
my
$q
=
sprintf
(
'SELECT * WHERE { { %s } } LIMIT 1'
,
join
(
'} UNION {'
,
@ids
));
my
$res
=
$self
->_get_json(
$config
->{endpoint}{sparql},
query
=> {
format
=>
'json'
,
query
=>
$q
});
my
$item
=
eval
{
$res
->{results}{bindings}[0]{item}};
return
undef
unless
$item
;
return
undef
unless
(
$item
->{type} //
''
) eq
'uri'
;
if
((
$item
->{value} //
''
) =~ m
return
$1;
}
}
return
undef
;
}
sub
_online_lookup__wikibase__stage_1 {
my
(
$self
,
$result
,
$id
,
$config
) =
@_
;
my
%ids
= (
$config
->{type} =>
$id
);
my
%attr
;
my
%res
= (
id
=> \
%ids
,
attributes
=> \
%attr
);
my
$data
=
$self
->_get_json(
sprintf
(
$config
->{endpoint}{entitydata},
$id
),
local_override
=> [
'%s.json'
,
$id
]);
$data
=
$data
->{entities}{
$id
};
$attr
{displayname} = {
map
{
$_
=>
$data
->{labels}{
$_
}{value}}
keys
%{
$data
->{labels}}};
$attr
{description} = {
map
{
$_
=>
$data
->{descriptions}{
$_
}{value}}
keys
%{
$data
->{descriptions}}};
$res
{wikidata_sitelinks} =
$data
->{sitelinks};
foreach
my
$property
(
keys
%{
$config
->{idmap}}) {
foreach
my
$entry
(@{
$data
->{claims}{
$property
} // []}) {
$ids
{
$config
->{idmap}{
$property
}} =
$entry
->{mainsnak}{datavalue}{value};
}
}
foreach
my
$special
(@{
$config
->{special_ids}}) {
foreach
my
$entry
(@{
$data
->{claims}{
$special
->{property}} // []}) {
$ids
{
$special
->{type}} //=
$special
->{from_service}->(
$entry
->{mainsnak}{datavalue}{value});
}
}
foreach
my
$attribute
(@{
$config
->{attributes}}) {
foreach
my
$entry
(@{
$data
->{claims}{
$attribute
->{property}} // []}) {
if
(
defined
$attribute
->{from_service}) {
my
%res
=
$attribute
->{from_service}->(
$entry
->{mainsnak}{datavalue}{value},
$config
);
$attr
{
$_
} //=
$res
{
$_
}
foreach
keys
%res
;
}
elsif
(
defined
$attribute
->{list_value}) {
my
%res
=
$attribute
->{list_value}->(
$entry
->{mainsnak}{datavalue}{value},
$config
);
foreach
my
$key
(
keys
%res
) {
$attr
{
$key
} //= [];
push
(@{
$attr
{
$key
}}, @{
$res
{
$key
}});
}
}
}
}
return
\
%res
;
}
sub
_online_lookup__wikibase__from_service__datetime {
my
(
$key
,
$value
) =
@_
;
my
$precision
=
$value
->{precision};
if
(
$precision
>= 9) {
my
$dt
= DateTime::Format::ISO8601->parse_datetime(
$value
->{
time
} =~ s/^\+//r =~ s/-00-00T/-01-01T/r =~ s/-00T/-01T/r);
my
$val
;
if
(
$precision
== 9) {
$val
=
$dt
->year;
}
elsif
(
$precision
== 10) {
$val
=
sprintf
(
'%.4u-%.2u'
,
$dt
->year,
$dt
->month);
}
else
{
$val
=
$dt
->ymd;
}
return
(
$key
=>
$val
);
}
return
();
}
sub
_online_lookup__wikibase__from_service__coordinate {
my
(
$value
) =
@_
;
my
%attr
;
foreach
my
$subkey
(
qw(altitude latitude longitude)
) {
$attr
{
$subkey
} = {
'*'
=>
$value
->{
$subkey
} + 0}
if
defined
$value
->{
$subkey
};
}
$attr
{space_object} = {
'*'
=> URI->new(
$value
->{globe})}
if
defined
$value
->{globe};
return
%attr
;
}
sub
_online_lookup__wikimedia_commons {
my
(
$self
,
$result
) =
@_
;
my
$res
= {
'attributes'
=> {},
};
my
$json
=
$self
->_get_json(
query
=> {
action
=>
'query'
,
titles
=>
$result
->id,
prop
=>
'imageinfo'
,
iiprop
=>
'url|mime|size|sha1|canonicaltitle'
,
iiurlwidth
=> 240,
format
=>
'json'
});
foreach
my
$page_id
(
keys
(%{
$json
->{query}->{pages} }) ) {
my
$page
=
$json
->{query}->{pages}->{
$page_id
};
my
$imageinfo
=
$page
->{imageinfo}->[0];
$res
->{attributes}->{displayname} = {
'*'
=>
$imageinfo
->{canonicaltitle} };
$res
->{attributes}->{thumbnail} = {
'*'
=> URI->new(
$imageinfo
->{thumburl}) };
$res
->{attributes}->{final_file_size} = {
'*'
=>
int
(
$imageinfo
->{size}) };
$res
->{attributes}->{media_subtype} = {
'*'
=>
$imageinfo
->{mime} };
$res
->{digest} = {
'sha-1-160'
=>
$imageinfo
->{sha1} };
}
return
$res
;
}
sub
_online_lookup__fellig {
my
(
$self
,
$result
) =
@_
;
my
Data::URIID
$extractor
=
$self
->extractor;
foreach
my
$type
(
@fellig_types
) {
my
$id
=
eval
{
$result
->id(
$type
,
_no_convert
=> 1)} //
next
;
foreach
my
$idx
(@{
$json
->{main_result}}) {
my
$tag
=
$json
->{tags}[
$idx
];
my
%ids
;
my
%attr
;
my
%res
= (
id
=> \
%ids
,
attributes
=> \
%attr
,
digest
=>
$tag
->{unvaried}{
'final-file-hash'
});
foreach
my
$class
(
qw(unvaried varied)
) {
foreach
my
$relation
(
'ids'
,
'tag-linked-by'
) {
foreach
my
$idtype
(
keys
%{
$tag
->{
$class
}{
$relation
}//{}}) {
if
(
$extractor
->is_ise(
$idtype
)) {
$ids
{
$idtype
} //=
$tag
->{
$class
}{
$relation
}{
$idtype
}[0];
}
}
}
$attr
{displayname} = {
'*'
=>
$tag
->{
$class
}{displayname}}
if
defined
$tag
->{
$class
}{displayname};
$attr
{icon_text} = {
'*'
=>
$tag
->{
$class
}{icontext}}
if
defined
$tag
->{
$class
}{icontext};
$attr
{displaycolour} = {
'*'
=> Data::URIID::Colour->new(
rgb
=>
$tag
->{
$class
}{displaycolour})}
if
defined
$tag
->{
$class
}{displaycolour};
$attr
{final_file_size}= {
'*'
=>
$tag
->{
$class
}{
'final-file-size'
}}
if
defined
$tag
->{
$class
}{
'final-file-size'
};
$attr
{icon} = {
'*'
=> URI->new(
$tag
->{
$class
}{icon})}
if
defined
$tag
->{
$class
}{icon};
if
(
defined
$tag
->{
$class
}{
'final-file-encoding'
}) {
if
(
defined
(
my
$wk
= _own_well_known()->{uuid}{
$tag
->{
$class
}{
'final-file-encoding'
}})) {
if
(
defined
(
my
$media_subtype
=
$wk
->{ids}{
'media-subtype-identifier'
})) {
$attr
{media_subtype} =
$media_subtype
;
}
}
}
}
return
\
%res
;
}
}
return
undef
;
}
sub
_online_lookup__noembed_com {
my
(
$self
,
$result
) =
@_
;
foreach
my
$service
(
qw(youtube)
) {
my
$url
=
eval
{
$result
->url(
service
=>
$service
,
action
=>
'render'
)} //
eval
{
$result
->url(
$service
,
action
=>
'embed'
)} //
next
;
my
%attr
;
my
%res
= (
attributes
=> \
%attr
);
$attr
{displayname} = {
'*'
=>
$json
->{title}}
if
defined
$json
->{title};
$attr
{thumbnail} = {
'*'
=> URI->new(
$json
->{thumbnail_url})}
if
defined
$json
->{thumbnail_url};
return
\
%res
;
}
return
undef
;
}
sub
_online_lookup__osm__handle {
my
(
$self
,
$element
) =
@_
;
my
$tags
=
$element
->{tags} // {};
my
%ids
;
my
%attr
;
my
%res
= (
id
=> \
%ids
,
attributes
=> \
%attr
);
$attr
{latitude} = {
'*'
=>
$element
->{lat} + 0}
if
defined
$element
->{lat};
$attr
{longitude} = {
'*'
=>
$element
->{lon} + 0}
if
defined
$element
->{lon};
$attr
{altitude} = {
'*'
=>
$tags
->{ele} + 0}
if
defined
$tags
->{ele};
$attr
{altitude} = {
'*'
=>
$tags
->{
'ele:wgs84'
} + 0}
if
defined
$tags
->{
'ele:wgs84'
};
$ids
{
'wikidata-identifier'
} =
$tags
->{wikidata}
if
defined
$tags
->{wikidata};
foreach
my
$key
(
keys
%attrmap_osm
) {
my
%data
;
$data
{
'*'
} =
$tags
->{
$key
}
if
defined
$tags
->{
$key
};
foreach
my
$inkey
(
keys
%{
$tags
}) {
if
(
$inkey
=~ /^\Q
$key
\E:([a-z]{2,3})$/) {
$data
{$1} =
$tags
->{
$inkey
};
}
}
$attr
{
$attrmap_osm
{
$key
}} = \
%data
if
scalar
keys
%data
;
}
return
\
%res
;
}
sub
_online_lookup__osm {
my
(
$self
,
$result
) =
@_
;
foreach
my
$type
(
qw(node way relation)
) {
my
$id
=
eval
{
$result
->id(
'osm-'
.
$type
)} //
next
;
my
$element
=
eval
{
$json
->{elements}[0]} //
return
undef
;
return
$self
->_online_lookup__osm__handle(
$element
);
}
return
undef
;
}
sub
_online_lookup__overpass {
my
(
$self
,
$result
) =
@_
;
my
$id
=
$result
->id(
'wikidata-identifier'
);
data
=>
sprintf
(
"[out:json][timeout:25];\n(node[\"wikidata\"=\"%s\"];\nway[\"wikidata\"=\"%s\"];\nrelation[\"wikidata\"=\"%s\"];\n);\nout;"
,
$id
,
$id
,
$id
,
),
}) //
return
undef
;
my
$element
=
eval
{
$json
->{elements}[0]} //
return
undef
;
my
$res
=
$self
->_online_lookup__osm__handle(
$element
);
my
$type
=
$element
->{type} //
''
;
my
$id_new
=
$element
->{id} //
''
;
if
(
$type
eq
'node'
||
$type
eq
'way'
||
$type
eq
'relation'
) {
if
(
$id_new
=~ Data::URIID::Result->RE_UINT) {
$res
->{id}->{
'osm-'
.
$type
} =
$id_new
;
}
}
return
$res
;
}
sub
_online_lookup__xkcd {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$id
=
eval
{
$result
->id(
'xkcd-num'
)};
my
$json
=
$self
->_get_json(
$opts
{metadata_url} //
$result
->url(
service
=>
'xkcd'
,
action
=>
'metadata'
),
local_override
=> [
'%s.json'
,
$id
]) //
return
undef
;
my
%ids
;
my
%attr
;
my
%res
= (
id
=> \
%ids
,
attributes
=> \
%attr
);
$ids
{
'xkcd-num'
} =
int
(
$json
->{num})
if
defined
(
$json
->{num}) &&
$json
->{num} =~ Data::URIID::Result->RE_UINT;
$attr
{displayname} = {
'*'
=>
$json
->{title}}
if
defined
(
$json
->{title}) &&
length
(
$json
->{title});
return
\
%res
;
}
sub
_online_lookup__doi {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$json
=
$self
->_get_json(
$result
->url(
service
=>
'doi'
,
action
=>
'metadata'
)) //
return
undef
;
my
%attr
;
my
%res
= (
attributes
=> \
%attr
);
$attr
{displayname} = {
'*'
=>
$json
->{title}}
if
defined
(
$json
->{title}) &&
length
(
$json
->{title});
return
\
%res
;
}
sub
_online_lookup__iconclass {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$id
=
$result
->id(
'iconclass-identifier'
);
my
$json
=
$self
->_get_json(
$result
->url(
service
=>
'iconclass'
,
action
=>
'metadata'
),
local_override
=> [
'%s.jsonld'
,
$id
]) //
return
undef
;
my
$item
=
$json
->{graph}[0] //
return
undef
;
my
%displayname
;
my
%res
= (
attributes
=> {
displayname
=> \
%displayname
});
foreach
my
$key
(
'prefLabel'
,
'dc:subject'
) {
foreach
my
$entry
(@{
$item
->{
$key
}}) {
$displayname
{
$entry
->{lang}} //=
$entry
->{value};
}
}
$displayname
{
'*'
} =
$displayname
{en} //
$displayname
{de};
return
\
%res
;
}
sub
_online_lookup__e621 {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$json
=
$self
->_get_json(
$result
->url(
service
=>
'e621'
,
action
=>
'metadata'
)) //
return
undef
;
my
%ids
;
my
%attr
;
my
%digest
;
my
%res
= (
id
=> \
%ids
,
attributes
=> \
%attr
,
digest
=> \
%digest
);
return
undef
unless
scalar
(@{
$json
->{posts}}) == 1;
foreach
my
$post
(@{
$json
->{posts}}) {
my
$preview
=
$post
->{preview};
my
$file
=
$post
->{file};
$ids
{
'e621-post-identifier'
} =
int
(
$post
->{id});
$attr
{ext} = {
'*'
=>
$file
->{ext}}
if
defined
$file
->{ext};
$attr
{final_file_size} = {
'*'
=>
$file
->{size}}
if
defined
$file
->{size};
$attr
{thumbnail} = {
'*'
=>
$preview
->{url}}
if
defined
$preview
->{url};
$digest
{
'md-5-128'
} =
$file
->{md5}
if
defined
$file
->{md5};
}
return
\
%res
;
}
sub
_online_lookup__furaffinity {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$html
=
$self
->_get_html(
$result
->url(
service
=>
'furaffinity'
,
action
=>
'info'
)) //
return
undef
;
my
%attr
;
my
%res
= (
attributes
=> \
%attr
);
my
%raw
=
map
{
$_
->attr(
'property'
) =>
$_
->attr(
'content'
)}
$html
->findnodes(
'/html/head/meta[@property]'
);
$self
->_load_open_graph(\
%res
,
$html
, [
qw(title description image)
], {
image
=>
qr#^https://t\.furaffinity\.net/#
});
foreach
my
$download
(
$html
->findnodes(
'/html/body//div[@id="submission_page"]//a[text()="Download" and @href]'
)) {
my
$url
= URI->new(
$download
->attr(
'href'
),
'https'
);
$url
->scheme(
'https'
);
$url
=
$url
->as_string;
$res
{url_overrides} = {
'fetch'
=>
$url
,
'file-fetch'
=>
$url
,
};
}
return
\
%res
;
}
sub
_online_lookup__imgur {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$html
=
$self
->_get_html(
$result
->url(
service
=>
'imgur'
,
action
=>
'info'
)) //
return
undef
;
my
%attr
;
my
%res
= (
attributes
=> \
%attr
);
my
%raw
=
map
{
$_
->attr(
'name'
) =>
$_
->attr(
'content'
)}
$html
->findnodes(
'/html/head/meta[@name]'
);
$res
{url_overrides} = {};
$self
->_load_open_graph(\
%res
,
$html
, [
qw(title image)
]);
if
(
defined
(
$raw
{
'twitter:player:stream'
}) &&
length
(
$raw
{
'twitter:player:stream'
})) {
$res
{url_overrides}{
'stream-fetch'
} =
$raw
{
'twitter:player:stream'
};
}
return
\
%res
;
}
sub
_online_lookup__notalwaysright {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$html
=
$self
->_get_html(
$result
->url(
service
=>
'notalwaysright'
,
action
=>
'info'
)) //
return
undef
;
my
%attr
;
my
%res
= (
attributes
=> \
%attr
);
my
%raw
=
map
{
$_
->attr(
'property'
) =>
$_
->attr(
'content'
)}
$html
->findnodes(
'/html/head/meta[@property]'
);
$res
{url_overrides} = {};
$self
->_load_open_graph(\
%res
,
$html
, [
qw(title)
]);
if
(
defined
(
my
$url
=
$raw
{
'og:url'
})) {
if
(
length
(
$url
)) {
$res
{url_overrides}{
'info'
} =
$url
;
$res
{url_overrides}{
'render'
} =
$url
;
}
}
return
\
%res
;
}
sub
_online_lookup__ruthede {
my
(
$self
,
$result
,
%opts
) =
@_
;
my
$html
=
$self
->_get_html(
$result
->url(
service
=>
'ruthede'
,
action
=>
'info'
)) //
return
undef
;
my
%attr
;
my
%res
= (
attributes
=> \
%attr
);
$self
->_load_open_graph(\
%res
,
$html
, [
qw(image)
]);
if
(
defined
(
$attr
{thumbnail}) &&
defined
(
my
$url
=
$attr
{thumbnail}{
'*'
})) {
if
(
$url
=~ m
$attr
{thumbnail} = {
'*'
=> $1.
'tn_'
.$2};
$res
{url_overrides} = {
'file-fetch'
=>
$url
,
};
}
}
return
\
%res
;
}
sub
displayname {
my
(
$self
,
%opts
) =
@_
;
return
$self
->name;
}
1;