|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package LinkEmbedder::Link;  | 
| 
2
 | 
30
 | 
 
 | 
 
 | 
  
30
  
 | 
 
 | 
218
 | 
 use Mojo::Base -base;  | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
    | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
202
 | 
    | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4
 | 
30
 | 
 
 | 
 
 | 
  
30
  
 | 
 
 | 
22509
 | 
 use Mojo::Template;  | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1241590
 | 
    | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
348
 | 
    | 
| 
5
 | 
30
 | 
 
 | 
 
 | 
  
30
  
 | 
 
 | 
1523
 | 
 use Mojo::Util 'trim';  | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
72
 | 
    | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2089
 | 
    | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
7
 | 
30
 | 
 
 | 
  
 50
  
 | 
  
30
  
 | 
 
 | 
201
 | 
 use constant DEBUG => $ENV{LINK_EMBEDDER_DEBUG} || 0;  | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
    | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
72335
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %DOM_SEL = (  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ':desc'      => ['meta[property="og:description"]', 'meta[name="twitter:description"]', 'meta[name="description"]'],  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ':image'     => ['meta[property="og:image"]',       'meta[property="og:image:url"]',    'meta[name="twitter:image"]'],  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ':site_name' => ['meta[property="og:site_name"]',   'meta[property="twitter:site"]'],  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ':title'     => ['meta[property="og:title"]',       'meta[name="twitter:title"]', 'title'],  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my @JSON_ATTRS = (  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'author_name',      'author_url',    'cache_age',       'height', 'provider_name', 'provider_url',  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'thumbnail_height', 'thumbnail_url', 'thumbnail_width', 'title',  'type',          'url',  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'version',          'width'  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has author_name     => undef;  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has author_url      => undef;  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has cache_age       => 0;  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has description     => '';  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has error           => undef;                                                # {message => "", code => ""}  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has force_secure    => 0;  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has height          => sub { $_[0]->type =~ /^photo|video$/ ? 0 : undef };  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has placeholder_url => '';  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has provider_name => sub {  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return undef unless my $name = shift->url->host;  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return $name =~ /([^\.]+)\.(\w+)$/ ? ucfirst $1 : $name;  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 };  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has provider_url     => sub { $_[0]->url->host ? $_[0]->url->clone->path('/') : undef };  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has template         => sub { [__PACKAGE__, sprintf '%s.html.ep', $_[0]->type] };  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has thumbnail_height => undef;  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has thumbnail_url    => undef;  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has thumbnail_width  => undef;  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has title            => undef;  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has type             => 'link';  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has ua               => undef;                                                             # Mojo::UserAgent object  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has url              => sub { Mojo::URL->new };                                            # Mojo::URL  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has version          => '1.0';  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has width            => sub { $_[0]->type =~ /^photo|video$/ ? 0 : undef };  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub html {  | 
| 
49
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
  
1
  
 | 
3069
 | 
   my $self     = shift;  | 
| 
50
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
   my $template = Mojo::Loader::data_section(@{$self->template}) or return '';  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
    | 
| 
51
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1583
 | 
   my $output   = Mojo::Template->new({auto_escape => 1, prepend => 'my $l=shift'})->render($template, $self);  | 
| 
52
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
31041
 | 
   die $output if ref $output;  | 
| 
53
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
   return $output;  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub learn_p {  | 
| 
57
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
13
 | 
   my $self = shift;  | 
| 
58
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
23
 | 
   return $self->_get_p($self->url)->then(sub { $self->_learn(shift) });  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
737
 | 
    | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub TO_JSON {  | 
| 
62
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
0
  
 | 
15
 | 
   my $self = shift;  | 
| 
63
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   my %json;  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
65
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   for my $attr (grep { defined $self->$_ } @JSON_ATTRS) {  | 
| 
 
 | 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1135
 | 
    | 
| 
66
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2468
 | 
     $json{$attr} = $self->$attr;  | 
| 
67
 | 
32
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
268
 | 
     $json{$attr} = "$json{$attr}" if $attr =~ /url$/;  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
70
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
   $json{html} = $self->html unless $self->type eq 'link';  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
72
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
   return \%json;  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
75
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
 sub _dump { Mojo::Util::dumper($_[0]->TO_JSON); }  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _el {  | 
| 
78
 | 
28
 | 
 
 | 
 
 | 
  
28
  
 | 
 
 | 
71
 | 
   my ($self, $dom, @sel) = @_;  | 
| 
79
 | 
28
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
144
 | 
   @sel = @{$DOM_SEL{$sel[0]}} if $DOM_SEL{$sel[0]};  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
    | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
81
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
   for my $sel (@sel) {  | 
| 
82
 | 
52
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
7523
 | 
     my $e     = $dom->at($sel) or next;  | 
| 
83
 | 
4
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
1203
 | 
     my ($val) = grep {$_} map { trim($_ // '') } $e->{content}, $e->{value}, $e->{href}, $e->text, $e->all_text;  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
770
 | 
    | 
| 
84
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
75
 | 
     return $val if defined $val;  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
87
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8701
 | 
   return '';  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _get_p {  | 
| 
91
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
45
 | 
   my ($self, $url) = @_;  | 
| 
92
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   $url = $url->clone->scheme('https') if $self->force_secure;  | 
| 
93
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
   warn sprintf "[%s] GET %s\n", ref($self), $url if DEBUG;  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return $self->ua->get_p($url)->then(sub {  | 
| 
95
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
44214
 | 
     my $tx = shift;  | 
| 
96
 | 
5
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
37
 | 
     $self->url->scheme('https') if $self->force_secure and $tx->res->is_success;  | 
| 
97
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52
 | 
     return $tx;  | 
| 
98
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
   });  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _learn {  | 
| 
102
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
18
 | 
   my ($self, $tx) = @_;  | 
| 
103
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
   my $h = $tx->res->headers;  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
105
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
114
 | 
   my $name = $h->header('X-Provider-Name');  | 
| 
106
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
68
 | 
   $self->provider_name($name) if $name;  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
108
 | 
5
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
23
 | 
   my $ct = $h->content_type || '';  | 
| 
109
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
71
 | 
   $self->type('photo')->_learn_from_url               if $ct =~ m!^image/!;  | 
| 
110
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   $self->type('video')->_learn_from_url               if $ct =~ m!^video/!;  | 
| 
111
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
29
 | 
   $self->type('rich')->_learn_from_text($tx)          if $ct =~ m!^text/plain!;  | 
| 
112
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
48
 | 
   $self->type('rich')->_learn_from_dom($tx->res->dom) if $ct =~ m!^text/html!;  | 
| 
113
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
   my $p = $self->_maybe_rebless_p($tx);  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
115
 | 
5
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
57
 | 
   return $p || $self;  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _learn_from_dom {  | 
| 
119
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
13
 | 
   my ($self, $dom) = @_;  | 
| 
120
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   my $v;  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
122
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   $self->author_name($v)      if $v = $self->_el($dom, '[itemprop="author"] [itemprop="name"]');  | 
| 
123
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
   $self->author_url($v)       if $v = $self->_el($dom, '[itemprop="author"] [itemprop="email"]');  | 
| 
124
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
52
 | 
   $self->description($v)      if $v = $self->_el($dom, ':desc');  | 
| 
125
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
   $self->thumbnail_height($v) if $v = $self->_el($dom, 'meta[property="og:image:height"]');  | 
| 
126
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
   $self->thumbnail_url($v)    if $v = $self->_el($dom, ':image');  | 
| 
127
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
   $self->thumbnail_width($v)  if $v = $self->_el($dom, 'meta[property="og:image:width"]');  | 
| 
128
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
   $self->title($v)            if $v = $self->_el($dom, ':title');  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
130
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42
 | 
   return $self;  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _learn_from_json {  | 
| 
134
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   my ($self, $tx) = @_;  | 
| 
135
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $json = $tx->res->json;  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
137
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   warn "[LinkEmbedder] " . $tx->res->text . "\n" if DEBUG;  | 
| 
138
 | 
  
0
  
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
   $self->{$_} ||= $json->{$_} for keys %$json;  | 
| 
139
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
   $self->{error}       = {message => $self->{error}} if defined $self->{error} and !ref $self->{error};  | 
| 
140
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
   $self->{error}{code} = $self->{status}             if $self->{status}        and $self->{status} =~ /^\d+$/;  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
142
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return $self;  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _learn_from_text {  | 
| 
146
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
17
 | 
   my ($self, $tx) = @_;  | 
| 
147
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   $self->_learn_from_url;  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
149
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
90
 | 
   $self->{paste} = $tx->res->text;  | 
| 
150
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
   $self->template->[1] = 'paste.html.ep';  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
152
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   my $title = substr $self->{paste}, 0, 20;  | 
| 
153
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   $title =~ s![\r\n]+! !g;  | 
| 
154
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   $self->title($title);  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _learn_from_url {  | 
| 
158
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
3
 | 
   my $self = shift;  | 
| 
159
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   my $path = $self->url->path;  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
161
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
   return $self->title(@$path ? $path->[-1] : 'Image');  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # TODO: Not sure if this is the best solution  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _maybe_rebless_p {  | 
| 
166
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
18
 | 
   my ($self, $tx) = @_;  | 
| 
167
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
22
 | 
   return unless ref $self eq 'LinkEmbedder::Link::Basic';  | 
| 
168
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   return unless $self->type eq 'rich';  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
170
 | 
5
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
48
 | 
   if ($self->title eq 'Jitsi Meet' or $tx->res->body =~ m!\bJitsiMeetJS\b!) {  | 
| 
171
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     require LinkEmbedder::Link::Jitsi;  | 
| 
172
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bless $self, 'LinkEmbedder::Link::Jitsi';  | 
| 
173
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self->learn_p;  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
176
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
364
 | 
   return;  | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =encoding utf8  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 LinkEmbedder::Link - Meta information for an URL  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 See L.  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 DESCRIPTION  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L is a class representing an expanded URL.  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 ATTRIBUTES  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 author_name  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $str = $self->author_name;  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Might hold the name of the author of L.  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 author_url  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $str = $self->author_name;  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Might hold an URL to the author.  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 cache_age  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $int = $self->cache_age;  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The suggested cache lifetime for this resource, in seconds.  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 description  | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $str = $self->description;  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Description of the L. Might be C.  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 error  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $hash_ref = $self->author_name;  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C on success, hash-ref on error. Example:  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   {message => "Oops!", code => 500};  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 force_secure  | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $bool = $self->force_secure;  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $self = $self->force_secure(1);  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This attribute will translate any unknown http link to https.  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This attribute is EXPERIMENTAL. Feeback appreciated.  | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 height  | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $int = $self->height;  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The height of L |