acts_as_unvlogable 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +2 -0
- data/.travis.yml +19 -0
- data/Gemfile +4 -9
- data/README.markdown +5 -29
- data/Rakefile +1 -1
- data/acts_as_unvlogable.gemspec +10 -8
- data/lib/acts_as_unvlogable.rb +63 -37
- data/lib/acts_as_unvlogable/flickr.rb +3 -487
- data/lib/acts_as_unvlogable/string_extend.rb +0 -1
- data/lib/acts_as_unvlogable/version.rb +1 -1
- data/lib/acts_as_unvlogable/vg_11870.rb +7 -18
- data/lib/acts_as_unvlogable/vg_blip.rb +4 -9
- data/lib/acts_as_unvlogable/vg_collegehumor.rb +8 -20
- data/lib/acts_as_unvlogable/vg_dailymotion.rb +3 -7
- data/lib/acts_as_unvlogable/vg_dalealplay.rb +7 -10
- data/lib/acts_as_unvlogable/vg_flickr.rb +2 -16
- data/lib/acts_as_unvlogable/vg_metacafe.rb +2 -21
- data/lib/acts_as_unvlogable/vg_myspace.rb +6 -12
- data/lib/acts_as_unvlogable/vg_pleer.rb +38 -0
- data/lib/acts_as_unvlogable/vg_rutube.rb +7 -51
- data/lib/acts_as_unvlogable/vg_ted.rb +8 -16
- data/lib/acts_as_unvlogable/vg_vimeo.rb +14 -22
- data/lib/acts_as_unvlogable/vg_wistia.rb +49 -0
- data/lib/acts_as_unvlogable/vg_youtu.rb +11 -0
- data/lib/acts_as_unvlogable/vg_youtube.rb +11 -22
- data/spec/acts_as_unvlogable_spec.rb +363 -0
- data/spec/spec_helper.rb +4 -0
- metadata +106 -108
- data/lib/acts_as_unvlogable/vg_marca.rb +0 -48
- data/lib/acts_as_unvlogable/vg_mtvmusic.rb +0 -65
- data/lib/acts_as_unvlogable/vg_qik.rb +0 -66
- data/test/acts_as_unvlogable_test.rb +0 -392
@@ -7,18 +7,16 @@
|
|
7
7
|
class Vg11870
|
8
8
|
|
9
9
|
def initialize(url=nil, options={})
|
10
|
-
@url = url
|
11
|
-
@page =
|
12
|
-
@flashvars = get_hash(/var flashvars = \{(.+)\}/.match(@page.to_s)[1])
|
13
|
-
@flashvars['logo'] = "http://11870.com#{@flashvars['logo']}" unless @flashvars['logo'].blank?
|
10
|
+
@url = url.sub "http:", "https:"
|
11
|
+
@page = Nokogiri::HTML(open(@url))
|
14
12
|
end
|
15
13
|
|
16
14
|
def title
|
17
|
-
CGI::unescapeHTML @page.
|
15
|
+
CGI::unescapeHTML @page.xpath("//span[@itemprop='name']").first.text.strip
|
18
16
|
end
|
19
17
|
|
20
18
|
def thumbnail
|
21
|
-
@
|
19
|
+
@page.xpath("//img[@itemprop='image']").first["src"]
|
22
20
|
end
|
23
21
|
|
24
22
|
def duration
|
@@ -26,16 +24,15 @@ class Vg11870
|
|
26
24
|
end
|
27
25
|
|
28
26
|
def embed_url
|
29
|
-
|
30
|
-
"http://11870.com/multimedia/flvplayer.swf?#{query}"
|
27
|
+
"https://s3-eu-west-1.amazonaws.com/static.11870.com/11870/player.swf?netstreambasepath=#{@url}&id=video&file=#{flv}&image=#{thumbnail}"
|
31
28
|
end
|
32
29
|
|
33
|
-
def embed_html(width=425, height=344, options={})
|
30
|
+
def embed_html(width=425, height=344, options={}, params={})
|
34
31
|
"<object width='#{width}' height='#{height}' classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0'> <param name='movie' value='#{embed_url}' /> <param name='quality' value='high' /><embed src='#{embed_url}' width='#{width}' height='#{height}' quality='high' type='application/x-shockwave-flash' pluginspage='http://www.macromedia.com/go/getflashplayer'/></object>"
|
35
32
|
end
|
36
33
|
|
37
34
|
def flv
|
38
|
-
@
|
35
|
+
@page.xpath("//div[@id='video']/span").first.text.strip
|
39
36
|
end
|
40
37
|
|
41
38
|
def download_url
|
@@ -46,12 +43,4 @@ class Vg11870
|
|
46
43
|
"11870.com"
|
47
44
|
end
|
48
45
|
|
49
|
-
protected
|
50
|
-
|
51
|
-
def get_hash(string)
|
52
|
-
pieces = string.gsub('"', '').split(/,|:\s/)
|
53
|
-
hash = Hash[*pieces]
|
54
|
-
hash.delete_if { |key, value| value.nil? || key == "displaywidth" }
|
55
|
-
end
|
56
|
-
|
57
46
|
end
|
@@ -17,7 +17,7 @@ class VgBlip
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def thumbnail
|
20
|
-
REXML::XPath.first(@feed, "//
|
20
|
+
REXML::XPath.first(@feed, "//media:thumbnail").attributes['url']
|
21
21
|
end
|
22
22
|
|
23
23
|
def duration
|
@@ -25,18 +25,13 @@ class VgBlip
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def embed_url
|
28
|
-
emb = REXML::XPath.first(@feed, "//
|
29
|
-
emb.split("src=\"")[1].split("\"")[0]
|
28
|
+
emb = REXML::XPath.first(@feed, "//blip:embedUrl")[0].to_s
|
30
29
|
end
|
31
30
|
|
32
|
-
def embed_html(width=425, height=344, options={})
|
33
|
-
"<
|
31
|
+
def embed_html(width=425, height=344, options={}, params={})
|
32
|
+
"<iframe src='#{embed_url}.x?p=1' width='#{width}' height='#{height}' frameborder='0' allowfullscreen></iframe>"
|
34
33
|
end
|
35
34
|
|
36
|
-
def flv
|
37
|
-
REXML::XPath.first(@feed, "//enclosure").attributes['url']
|
38
|
-
end
|
39
|
-
|
40
35
|
def download_url
|
41
36
|
nil
|
42
37
|
end
|
@@ -9,7 +9,7 @@ class VgCollegehumor
|
|
9
9
|
def initialize(url=nil, options={})
|
10
10
|
@url = url
|
11
11
|
@video_id = parse_url(url)
|
12
|
-
res = Net::HTTP.get(URI.parse("http://www.collegehumor.com/moogaloop/video
|
12
|
+
res = Net::HTTP.get(URI.parse("http://www.collegehumor.com/moogaloop/video/#{@video_id}"))
|
13
13
|
@feed = REXML::Document.new(res)
|
14
14
|
end
|
15
15
|
|
@@ -22,17 +22,13 @@ class VgCollegehumor
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def embed_url
|
25
|
-
"http://www.collegehumor.com/
|
25
|
+
"http://www.collegehumor.com/e/#{@video_id}"
|
26
26
|
end
|
27
27
|
|
28
|
-
def embed_html(width=425, height=344, options={})
|
29
|
-
"<
|
28
|
+
def embed_html(width=425, height=344, options={}, params={})
|
29
|
+
"<iframe src='#{embed_url}' width='#{width}' height='#{height}' frameborder='0' webkitAllowFullScreen allowFullScreen></iframe>"
|
30
30
|
end
|
31
31
|
|
32
|
-
def flv
|
33
|
-
REXML::XPath.first(@feed, "//video/file")[0]
|
34
|
-
end
|
35
|
-
|
36
32
|
def download_url
|
37
33
|
nil
|
38
34
|
end
|
@@ -46,21 +42,13 @@ class VgCollegehumor
|
|
46
42
|
end
|
47
43
|
|
48
44
|
private
|
49
|
-
|
45
|
+
|
50
46
|
def parse_url(url)
|
51
47
|
uri = URI.parse(url)
|
52
48
|
path = uri.path
|
53
|
-
videoargs =
|
54
|
-
|
55
|
-
|
56
|
-
raise unless videoargs.size > 0 && videoargs.first == '/video'
|
57
|
-
else
|
58
|
-
raise
|
59
|
-
end
|
60
|
-
videoargs[1]
|
61
|
-
rescue
|
62
|
-
nil
|
49
|
+
videoargs = path.split("/")
|
50
|
+
raise unless videoargs.size > 0 && videoargs[1] == 'video'
|
51
|
+
videoargs[2]
|
63
52
|
end
|
64
53
|
|
65
|
-
|
66
54
|
end
|
@@ -22,17 +22,13 @@ class VgDailymotion
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def embed_url
|
25
|
-
REXML::XPath.first(@feed, "//media:content[@type='
|
25
|
+
REXML::XPath.first(@feed, "//media:content[@type='text/html']").attributes['url']
|
26
26
|
end
|
27
27
|
|
28
|
-
def embed_html(width=425, height=344, options={})
|
29
|
-
"<
|
28
|
+
def embed_html(width=425, height=344, options={}, params={})
|
29
|
+
"<iframe frameborder='0' width='#{width}' height='#{height}' src='#{embed_url}' allowfullscreen></iframe>"
|
30
30
|
end
|
31
31
|
|
32
|
-
def flv
|
33
|
-
REXML::XPath.first(@feed, "//media:content[@type='video/x-flv']").attributes['url']
|
34
|
-
end
|
35
|
-
|
36
32
|
def download_url
|
37
33
|
nil
|
38
34
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
# ----------------------------------------------
|
2
3
|
# Class for dalealplay (dalealplay.com)
|
3
4
|
# http://www.dalealplay.com/informaciondecontenido.php?con=80280
|
@@ -11,33 +12,29 @@ class VgDalealplay
|
|
11
12
|
def initialize(url=nil, options={})
|
12
13
|
@url = url
|
13
14
|
@video_id = @url.query_param('con')
|
14
|
-
@page =
|
15
|
+
@page = Nokogiri::HTML(open(@url))
|
15
16
|
end
|
16
17
|
|
17
18
|
def title
|
18
|
-
|
19
|
+
@page.xpath("//h1").first.text
|
19
20
|
end
|
20
21
|
|
21
22
|
def thumbnail
|
22
|
-
"
|
23
|
+
@page.xpath("//meta[@itemprop='image']").first["content"]
|
23
24
|
end
|
24
25
|
|
25
26
|
def embed_url
|
26
|
-
@page.
|
27
|
+
@page.xpath("//meta[@itemprop='embedUrl']").first["content"]
|
27
28
|
end
|
28
29
|
|
29
30
|
def duration
|
30
31
|
nil
|
31
32
|
end
|
32
33
|
|
33
|
-
def embed_html(width=425, height=344, options={})
|
34
|
-
"<
|
34
|
+
def embed_html(width=425, height=344, options={}, params={})
|
35
|
+
"<iframe frameborder='0' marginwidth='0' marginheight ='0' id='videodap' scrolling='no' width='#{width}' height='#{height}' src='#{embed_url}'></iframe>"
|
35
36
|
end
|
36
37
|
|
37
|
-
def flv
|
38
|
-
"http://videos.dalealplay.com/contenidos3/#{CGI::parse(URI::parse(embed_url).query)['file']}"
|
39
|
-
end
|
40
|
-
|
41
38
|
def download_url
|
42
39
|
nil
|
43
40
|
end
|
@@ -26,25 +26,11 @@ class VgFlickr
|
|
26
26
|
def embed_url
|
27
27
|
"http://www.flickr.com/apps/video/stewart.swf?v=63881&intl_lang=en-us&photo_secret=#{@details.secret}&photo_id=#{@video_id}"
|
28
28
|
end
|
29
|
-
|
30
|
-
def embed_html(width=425, height=344, options={})
|
29
|
+
|
30
|
+
def embed_html(width=425, height=344, options={}, params={})
|
31
31
|
"<object type='application/x-shockwave-flash' width='#{width}' height='#{height}' data='http://www.flickr.com/apps/video/stewart.swf?v=63881' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'><param name='movie' value='#{embed_url}'></param> <param name='bgcolor' value='#000000'></param> <param name='allowFullScreen' value='true'></param><embed type='application/x-shockwave-flash' src='#{embed_url}' bgcolor='#000000' allowfullscreen='true' width='#{width}' height='#{height}'></embed></object>"
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
def flv
|
36
|
-
player_feed = "http://www.flickr.com/apps/video/video_mtl_xml.gne?v=x&photo_id=#{@video_id}&secret=#{@details.secret}&olang=en-us&noBuffer=null&bitrate=700&target=_blank"
|
37
|
-
res = Net::HTTP.get(URI::parse(player_feed))
|
38
|
-
player_feed_xml = REXML::Document.new(res)
|
39
|
-
data_id = REXML::XPath.first(player_feed_xml, "//Data/Item[@id='id']")[0].to_s
|
40
|
-
|
41
|
-
video_feed = "http://www.flickr.com/video_playlist.gne?node_id=#{data_id}&tech=flash&mode=playlist&lq=j2CW2jbpqCLKRy_s4bTylH&bitrate=700&secret=#{@details.secret}&rd=video.yahoo.com-offsite&noad=1"
|
42
|
-
res = Net::HTTP.get(URI::parse(video_feed))
|
43
|
-
video_feed_xml = REXML::Document.new(res)
|
44
|
-
stream = REXML::XPath.first(video_feed_xml, "//DATA/SEQUENCE-ITEM/STREAM")
|
45
|
-
"#{stream.attributes['APP']}#{stream.attributes['FULLPATH']}"
|
46
|
-
end
|
47
|
-
|
48
34
|
def download_url
|
49
35
|
nil
|
50
36
|
end
|
@@ -9,8 +9,6 @@ class VgMetacafe
|
|
9
9
|
def initialize(url=nil, options={})
|
10
10
|
@url = url
|
11
11
|
@args = parse_url(url)
|
12
|
-
|
13
|
-
#is the video 'youtubed'?
|
14
12
|
@youtubed = @args[1].index("yt-").nil? ? false : true
|
15
13
|
@yt = @youtubed ? VgYoutube.new("http://www.youtube.com/watch?v=#{@args[1].sub('yt-', '')}") : nil
|
16
14
|
end
|
@@ -27,30 +25,14 @@ class VgMetacafe
|
|
27
25
|
"http://www.metacafe.com/fplayer/#{@args[1]}/#{@args[2]}.swf"
|
28
26
|
end
|
29
27
|
|
30
|
-
def embed_html(width=425, height=344, options={})
|
31
|
-
"<
|
28
|
+
def embed_html(width=425, height=344, options={}, params={})
|
29
|
+
"<iframe src='#{embed_url}' width='#{width}' height='#{height}' allowFullScreen frameborder=0></iframe>"
|
32
30
|
end
|
33
31
|
|
34
|
-
def flv
|
35
|
-
if @youtubed
|
36
|
-
@yt.flv
|
37
|
-
else
|
38
|
-
params = Hash.new
|
39
|
-
open(self.embed_url) {|f|
|
40
|
-
params = CGI::parse(f.base_uri.request_uri.split("?")[1])
|
41
|
-
}
|
42
|
-
CGI::unescape "#{ params['mediaURL']}?__gda__=#{params['gdaKey']}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
32
|
def duration
|
47
33
|
nil
|
48
34
|
end
|
49
35
|
|
50
|
-
def download_url
|
51
|
-
nil
|
52
|
-
end
|
53
|
-
|
54
36
|
def service
|
55
37
|
"Metacafe"
|
56
38
|
end
|
@@ -64,7 +46,6 @@ class VgMetacafe
|
|
64
46
|
if path and path.split("/").size >=1
|
65
47
|
@args = path.split("/")
|
66
48
|
@args.delete("watch")
|
67
|
-
|
68
49
|
raise unless @args.size > 0
|
69
50
|
else
|
70
51
|
raise
|
@@ -8,17 +8,15 @@ class VgMyspace
|
|
8
8
|
|
9
9
|
def initialize(url=nil, options={})
|
10
10
|
@url = url
|
11
|
-
@
|
12
|
-
res = Net::HTTP.get(URI.parse("http://mediaservices.myspace.com/services/rss.ashx?type=video&videoID=#{@video_id}"))
|
13
|
-
@feed = REXML::Document.new(res)
|
11
|
+
@page = Nokogiri::HTML(open(@url))
|
14
12
|
end
|
15
13
|
|
16
14
|
def title
|
17
|
-
|
15
|
+
@page.xpath("//meta[@property='og:title']").first["content"].split("Video by")[0].strip
|
18
16
|
end
|
19
17
|
|
20
18
|
def thumbnail
|
21
|
-
|
19
|
+
@page.xpath("//meta[@property='og:image']").first["content"].strip
|
22
20
|
end
|
23
21
|
|
24
22
|
def duration
|
@@ -26,17 +24,13 @@ class VgMyspace
|
|
26
24
|
end
|
27
25
|
|
28
26
|
def embed_url
|
29
|
-
|
27
|
+
@page.xpath("//meta[@name='twitter:player']").first["content"].strip
|
30
28
|
end
|
31
29
|
|
32
|
-
def embed_html(width=425, height=344, options={})
|
33
|
-
"<
|
30
|
+
def embed_html(width=425, height=344, options={}, params={})
|
31
|
+
"<iframe width='#{width}' height='#{height}' src='#{embed_url}' frameborder='0' allowtransparency='true' webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>"
|
34
32
|
end
|
35
33
|
|
36
|
-
def flv
|
37
|
-
REXML::XPath.first(@feed, "//media:content").attributes['url']
|
38
|
-
end
|
39
|
-
|
40
34
|
def download_url
|
41
35
|
nil
|
42
36
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class VgPleer
|
2
|
+
attr_accessor :track_id
|
3
|
+
|
4
|
+
def initialize(url, options={})
|
5
|
+
@uri = URI.parse(url)
|
6
|
+
@track_id = @uri.path.match(/tracks\/([\w\d]+)/)[1]
|
7
|
+
@url = url
|
8
|
+
raise ArgumentError unless @track_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def title
|
12
|
+
@title ||= [pp_data[:singer], pp_data[:song]].join(' - ')
|
13
|
+
end
|
14
|
+
|
15
|
+
def embed_html(width=425, height=344, options={}, params={})
|
16
|
+
"<object width=\"#{width}\" height=\"#{height}\"><param name=\"movie\" value=\"http://embed.pleer.com/track?id=#{track_id}\"></param><embed src=\"http://embed.pleer.com/track?id=#{track_id}\" type=\"application/x-shockwave-flash\" width=\"#{width}\" height=\"#{height}\"></embed></object>"
|
17
|
+
end
|
18
|
+
|
19
|
+
def service
|
20
|
+
"Pleer"
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def pp_data
|
25
|
+
return @pp_data if defined? @pp_data
|
26
|
+
page = Nokogiri::HTML(Net::HTTP.get(@uri))
|
27
|
+
info = page.xpath('//li[@singer]').first
|
28
|
+
@pp_data = {
|
29
|
+
:singer => info['singer'], # artist name
|
30
|
+
:song => info['song'], # song title
|
31
|
+
:file_id => info['file_id'], # wtf
|
32
|
+
:link => info['link'], # same as @track_id
|
33
|
+
:duration => info['duration'], # duration of the song in seconds
|
34
|
+
:size => info['size'], # file size
|
35
|
+
:rate => info['rate'] # bit rate
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
@@ -2,45 +2,23 @@ class VgRutube
|
|
2
2
|
|
3
3
|
def initialize(url=nil, options={})
|
4
4
|
@url = url
|
5
|
-
|
5
|
+
@page = Nokogiri::HTML(open(@url)) rescue nil
|
6
|
+
raise ArgumentError.new("Unsuported url or service") if @page.xpath("//meta[@property='og:video:iframe']").blank?
|
6
7
|
end
|
7
8
|
|
8
9
|
def title
|
9
|
-
|
10
|
+
@page.xpath("//meta[@property='og:title']").first["content"].strip
|
10
11
|
end
|
11
|
-
|
12
|
-
# this method of extraction is somewhat fragile to changes in RuTube urls
|
13
|
-
# more correct way would be using rt_info structure, like it was done in title()
|
14
12
|
def thumbnail
|
15
|
-
|
16
|
-
# I'm not sure how to add size parameter in compatible way
|
17
|
-
size = 2
|
18
|
-
"http://img.rutube.ru/thumbs/#{movie_hash[0,2]}/#{movie_hash[2,2]}/#{movie_hash}-#{size}.jpg"
|
13
|
+
@page.xpath("//meta[@property='og:image']").first["content"].strip
|
19
14
|
end
|
20
15
|
|
21
16
|
def embed_url
|
22
|
-
|
23
|
-
"http://video.rutube.ru/#{movie_hash}"
|
24
|
-
end
|
25
|
-
|
26
|
-
def embed_html(width=425, height=344, options={})
|
27
|
-
# overridden cause we have to change default size if needed
|
28
|
-
return <<-"END"
|
29
|
-
<object width="#{width}" height="#{height}"><param
|
30
|
-
name="movie" value="#{embed_url}"></param><param
|
31
|
-
name="wmode" value="window"></param><param
|
32
|
-
name="allowFullScreen" value="true"></param><embed
|
33
|
-
src="#{embed_url}" type="application/x-shockwave-flash"
|
34
|
-
wmode="window" width="#{width}" height="#{height}"
|
35
|
-
allowFullScreen="true"></embed>
|
36
|
-
</object>
|
37
|
-
END
|
17
|
+
@page.xpath("//meta[@property='og:video:iframe']").first["content"].strip
|
38
18
|
end
|
39
19
|
|
40
|
-
def
|
41
|
-
#
|
42
|
-
# can't be extracted from rt_info
|
43
|
-
"http://bl.rutube.ru/#{movie_hash}.iflv"
|
20
|
+
def embed_html(width=425, height=344, options={}, params={})
|
21
|
+
"<iframe width='#{width}' height='#{height}' src='#{embed_url}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowfullscreen></iframe>"
|
44
22
|
end
|
45
23
|
|
46
24
|
def download_url
|
@@ -55,26 +33,4 @@ class VgRutube
|
|
55
33
|
"Rutube"
|
56
34
|
end
|
57
35
|
|
58
|
-
private
|
59
|
-
|
60
|
-
attr_accessor :movie_id
|
61
|
-
RT_XML_API = "http://rutube.ru/cgi-bin/xmlapi.cgi"
|
62
|
-
|
63
|
-
def movie_hash
|
64
|
-
@movie_hash ||= rt_info["movie"][0]["playerLink"][0].match( %r{[a-f0-9]+$} )[0]
|
65
|
-
end
|
66
|
-
|
67
|
-
def rt_info
|
68
|
-
url = RT_XML_API + "?rt_movie_id=#{movie_id}&rt_mode=movie"
|
69
|
-
@rt_info ||= XmlSimple.xml_in( Net::HTTP.get_response( URI.parse(url) ).body )
|
70
|
-
end
|
71
|
-
|
72
|
-
def parse_url(url)
|
73
|
-
uri = URI.parse(url)
|
74
|
-
@movie_id = uri.path.match(/\d+/)[0]
|
75
|
-
# this doesn't work reliably:
|
76
|
-
# @movie_hash = uri.query.match(/(^|&)v=([^&]+)/)[2]
|
77
|
-
# we'll cut it from rt_info instead
|
78
|
-
end
|
79
|
-
|
80
36
|
end
|