anstaendig 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +7 -0
- data/bin/anstaendig +114 -0
- data/lib/anstaendig/abstractagent.rb +48 -0
- data/lib/anstaendig/agents/3sat.rb +31 -0
- data/lib/anstaendig/agents/ard.rb +49 -0
- data/lib/anstaendig/agents/arte.rb +49 -0
- data/lib/anstaendig/agents/zdf.rb +47 -0
- data/lib/anstaendig.rb +11 -0
- metadata +74 -0
data/README.rdoc
ADDED
data/bin/anstaendig
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Script to download videos from various streaming sites.
|
4
|
+
#
|
5
|
+
# Author:: henning mueller (mailto:henning@orgizm.net)
|
6
|
+
# Copyright:: Copyright (c) 2010 henning mueller
|
7
|
+
# License:: Beerware
|
8
|
+
|
9
|
+
require( 'uri' )
|
10
|
+
require( 'getoptlong' )
|
11
|
+
|
12
|
+
# Add source lib directory to include paths for require to work if anstaendig
|
13
|
+
# not installed as a gem.
|
14
|
+
$:.unshift( File.dirname( __FILE__ ) + '/../lib' )
|
15
|
+
require( 'anstaendig' )
|
16
|
+
include( Anstaendig )
|
17
|
+
|
18
|
+
# Shows a summary of the command line options.
|
19
|
+
def usageMessage
|
20
|
+
$stderr << "#{File.basename( $0 )} [options] <url>
|
21
|
+
Download videos from video streaming sites.
|
22
|
+
|
23
|
+
-h This help.
|
24
|
+
-l List available agents.
|
25
|
+
-m Keep mess (do not clean up on Interrupt).
|
26
|
+
-o name File to save the video to.
|
27
|
+
-q quality Quality of the video.
|
28
|
+
-r Recode to Theora/Vorbis.
|
29
|
+
-s Only show stream URL.
|
30
|
+
|
31
|
+
"
|
32
|
+
exit( 1 )
|
33
|
+
end
|
34
|
+
|
35
|
+
# Prints available download agents.
|
36
|
+
def listAgents
|
37
|
+
puts( AGENTS.keys.sort )
|
38
|
+
exit( 0 )
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns a new filename, if the desired one is taken.
|
42
|
+
def nextFilename( filename )
|
43
|
+
if( File.exists?( filename ) )
|
44
|
+
new = filename.insert( filename.index( /\./, -5 ), '.new' )
|
45
|
+
nextFilename( new )
|
46
|
+
else
|
47
|
+
return( filename )
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
options = GetoptLong.new(
|
52
|
+
[ '-h', GetoptLong::NO_ARGUMENT ],
|
53
|
+
[ '-l', GetoptLong::NO_ARGUMENT ],
|
54
|
+
[ '-m', GetoptLong::NO_ARGUMENT ],
|
55
|
+
[ '-o', GetoptLong::REQUIRED_ARGUMENT ],
|
56
|
+
[ '-q', GetoptLong::REQUIRED_ARGUMENT ],
|
57
|
+
[ '-r', GetoptLong::NO_ARGUMENT ],
|
58
|
+
[ '-s', GetoptLong::NO_ARGUMENT ]
|
59
|
+
)
|
60
|
+
|
61
|
+
saveAs = ""
|
62
|
+
quality = :default
|
63
|
+
cleanUp = true
|
64
|
+
recodeOGG, showStreamURL = false
|
65
|
+
|
66
|
+
options.each do |option, argument|
|
67
|
+
case( option )
|
68
|
+
when '-h'
|
69
|
+
usageMessage
|
70
|
+
when '-l'
|
71
|
+
listAgents
|
72
|
+
when '-m'
|
73
|
+
cleanUp = false
|
74
|
+
when '-o'
|
75
|
+
saveAs = argument
|
76
|
+
when '-q'
|
77
|
+
quality = argument.to_sym
|
78
|
+
when '-r'
|
79
|
+
recodeOGG = true
|
80
|
+
when '-s'
|
81
|
+
showStreamURL = true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
begin
|
86
|
+
uri = URI.parse( ARGV[0] )
|
87
|
+
rescue URI::InvalidURIError
|
88
|
+
usageMessage
|
89
|
+
end
|
90
|
+
|
91
|
+
agent = AGENTS[ uri.host ].new( uri, quality )
|
92
|
+
|
93
|
+
if( showStreamURL )
|
94
|
+
puts( agent.url )
|
95
|
+
exit( 0 )
|
96
|
+
end
|
97
|
+
|
98
|
+
if( saveAs.empty? )
|
99
|
+
agent.filename = nextFilename( agent.filename )
|
100
|
+
else
|
101
|
+
agent.filename = saveAs
|
102
|
+
end
|
103
|
+
|
104
|
+
begin
|
105
|
+
agent.run
|
106
|
+
rescue Interrupt
|
107
|
+
if( cleanUp and File.exists?( agent.filename ) )
|
108
|
+
File.unlink( agent.filename )
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
if( recodeOGG )
|
113
|
+
agent.recode
|
114
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Anstaendig
|
2
|
+
AGENTS = Hash.new
|
3
|
+
|
4
|
+
# This interface describes download agents.
|
5
|
+
class AbstractAgent
|
6
|
+
attr_accessor :filename, :url
|
7
|
+
|
8
|
+
# Exception should be thrown, if an non-existent quality is demanded
|
9
|
+
# by the user.
|
10
|
+
class NoSuchQualityException
|
11
|
+
end
|
12
|
+
|
13
|
+
# If an agent does not set @filename, it would be the current time
|
14
|
+
# and date.
|
15
|
+
def initialize( url, quality = :high )
|
16
|
+
@filename = Time.now.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
# Calls the ripping process after substitution of certain characters
|
20
|
+
# in the filename generated by the agent.
|
21
|
+
def run
|
22
|
+
[ '/', '"', "'" ].each do |char|
|
23
|
+
@filename.gsub!( char, '' )
|
24
|
+
end
|
25
|
+
|
26
|
+
rip
|
27
|
+
end
|
28
|
+
|
29
|
+
# Contains the subshell command to rip the video stream. mplayer by
|
30
|
+
# default. Meant to be overloaded by the agent if necessary.
|
31
|
+
def rip
|
32
|
+
`mplayer -user-agent "#{userAgent}" -dumpstream -dumpfile "#{@filename}" "#{@url}"`
|
33
|
+
end
|
34
|
+
|
35
|
+
# Contains the subshell command to recode the video to a Vorbis/Theora
|
36
|
+
# encoded video in an OGG container. Meant to be overloaded by the
|
37
|
+
# agent if necessary.
|
38
|
+
def recode
|
39
|
+
`ffmpeg -i "#{@filename}" -acodec libvorbis -vcodec libtheora "#{@filename}.ogg"`
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return the user agent which is sent on stream retrieval. Meant to be
|
43
|
+
# overloaded by the agent if necessary.
|
44
|
+
def userAgent
|
45
|
+
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.2) Gecko/20100323 Namoroka/3.6.2"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Anstaendig
|
2
|
+
# Agent for anstaendig to download videos from the 3sat media center.
|
3
|
+
#
|
4
|
+
# Author:: henning mueller (mailto:henning@orgizm.net)
|
5
|
+
# Copyright:: Copyright (c) 2010 henning mueller
|
6
|
+
# License:: Beerware
|
7
|
+
|
8
|
+
# 3sat agent class inherits from agent interface.
|
9
|
+
class DreiSatAgent < AbstractAgent
|
10
|
+
AGENTS[ 'www.3sat.de' ] = self
|
11
|
+
|
12
|
+
def initialize( uri, quality )
|
13
|
+
require( 'nokogiri' )
|
14
|
+
require( 'open-uri' )
|
15
|
+
require( 'iconv' )
|
16
|
+
|
17
|
+
uri.query += '&mode=play'
|
18
|
+
|
19
|
+
doc = Nokogiri::HTML( open( uri.to_s ) )
|
20
|
+
|
21
|
+
title = doc.xpath( '//title' ).inner_html
|
22
|
+
title = title.gsub!( '3sat.Mediathek - Video: ', '' ) + '.wmv'
|
23
|
+
|
24
|
+
asx = doc.xpath( '//embed[@id="Player2"]' ).attr( 'data' )
|
25
|
+
asx = Nokogiri::HTML( open( asx ) )
|
26
|
+
|
27
|
+
@filename = Iconv.conv( 'utf8', 'latin1', title )
|
28
|
+
@url = asx.xpath( '//ref' ).attr( 'href' )
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Anstaendig
|
2
|
+
# Agent for anstaendig to download videos from the ARD media center.
|
3
|
+
#
|
4
|
+
# Author:: henning mueller (mailto:henning@orgizm.net)
|
5
|
+
# Copyright:: Copyright (c) 2010 henning mueller
|
6
|
+
# License:: Beerware
|
7
|
+
|
8
|
+
# ARD agent class inherits from agent interface.
|
9
|
+
class ArdAgent < AbstractAgent
|
10
|
+
AGENTS[ 'www.ardmediathek.de' ] = self
|
11
|
+
|
12
|
+
def initialize( uri, quality )
|
13
|
+
require( 'nokogiri' )
|
14
|
+
require( 'open-uri' )
|
15
|
+
|
16
|
+
doc = Nokogiri::HTML( open( uri.to_s ) )
|
17
|
+
raw = doc.content.split( "\r\n" ).grep( /rtmp/ )
|
18
|
+
|
19
|
+
@url = case( quality )
|
20
|
+
when :high, :default
|
21
|
+
conjure( raw.last )
|
22
|
+
when :medium
|
23
|
+
begin
|
24
|
+
conjure( raw[1] )
|
25
|
+
rescue( NoMethodError )
|
26
|
+
raise( NoSuchQualityException )
|
27
|
+
end
|
28
|
+
when :low
|
29
|
+
conjure( raw.first )
|
30
|
+
else
|
31
|
+
raise( NoSuchQualityException )
|
32
|
+
end
|
33
|
+
|
34
|
+
title = doc.xpath( '//title' ).inner_text
|
35
|
+
title = title.gsub( 'ARD Mediathek: ', '' )
|
36
|
+
n = title.index( /\ -\ [A-Za-z]*,/ ) - 1
|
37
|
+
|
38
|
+
@filename = title[0..n] + '.flv'
|
39
|
+
end
|
40
|
+
|
41
|
+
def conjure( string )
|
42
|
+
a = string.index( '"' ) + 1
|
43
|
+
b = string.index( '", "' ) - 1
|
44
|
+
c = string.index( '")' ) - 1
|
45
|
+
|
46
|
+
string.slice( a..b ) + string.slice( b+5..c )
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Anstaendig
|
2
|
+
# Agent for anstaendig to download videos from the arte media center.
|
3
|
+
#
|
4
|
+
# Author:: henning mueller (mailto:henning@orgizm.net)
|
5
|
+
# Copyright:: Copyright (c) 2010 henning mueller
|
6
|
+
# License:: Beerware
|
7
|
+
|
8
|
+
#
|
9
|
+
# TODO
|
10
|
+
# This extracts the correct filename and url, but the stream ripping dies
|
11
|
+
# somehow after a few minutes.
|
12
|
+
#
|
13
|
+
|
14
|
+
# arte agent class inherits from agent interface.
|
15
|
+
class ArteAgent < AbstractAgent
|
16
|
+
AGENTS[ 'videos.arte.tv' ] = self
|
17
|
+
|
18
|
+
def initialize( uri, quality )
|
19
|
+
require( 'nokogiri' )
|
20
|
+
require( 'open-uri' )
|
21
|
+
|
22
|
+
lang = ENV['LANG'].slice(0..1)
|
23
|
+
|
24
|
+
doc = open( uri.to_s ).readlines
|
25
|
+
|
26
|
+
doc = Nokogiri::XML( open(
|
27
|
+
doc.grep( /vars_player\.videorefFileUrl/ )
|
28
|
+
.first.match( /(http.*xml)/ )[1]
|
29
|
+
))
|
30
|
+
|
31
|
+
doc.xpath( '//videos/video' ).each do |item|
|
32
|
+
if( item.attr( 'lang' ) == lang )
|
33
|
+
doc = Nokogiri::XML( open( item.attr( 'ref' ) ) )
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
@filename = doc.xpath( '//name' ).first.text + '.wmv'
|
38
|
+
|
39
|
+
case( quality )
|
40
|
+
when :hd, :high, :default
|
41
|
+
@url = doc.xpath( '//urls/url[@quality="hd"]' ).text
|
42
|
+
when :sd, :medium, :low
|
43
|
+
@url = doc.xpath( '//urls/url[@quality="sd"]' ).text
|
44
|
+
else
|
45
|
+
raise( NoSuchQualityException )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Anstaendig
|
2
|
+
# Agent for anstaendig to download videos from the ZDF media center.
|
3
|
+
#
|
4
|
+
# Author:: henning mueller (mailto:henning@orgizm.net)
|
5
|
+
# Copyright:: Copyright (c) 2010 henning mueller
|
6
|
+
# License:: Beerware
|
7
|
+
|
8
|
+
# ZDF agent class inherits from agent interface.
|
9
|
+
class ZdfAgent < AbstractAgent
|
10
|
+
AGENTS[ 'www.zdf.de' ] = self
|
11
|
+
|
12
|
+
def initialize( uri, quality )
|
13
|
+
require( 'nokogiri' )
|
14
|
+
require( 'open-uri' )
|
15
|
+
|
16
|
+
uri = uri.to_s
|
17
|
+
|
18
|
+
if( uri =~ /hauptnavigation\/startseite\/#/ )
|
19
|
+
uri.gsub!( 'hauptnavigation/startseite/#/', '' )
|
20
|
+
end
|
21
|
+
|
22
|
+
doc = Nokogiri::HTML( open( uri ) )
|
23
|
+
|
24
|
+
quality = case( quality )
|
25
|
+
when :high, :default
|
26
|
+
'/veryhigh/'
|
27
|
+
when :medium, :low
|
28
|
+
'/300/'
|
29
|
+
else
|
30
|
+
raise( NoSuchQualityException )
|
31
|
+
end
|
32
|
+
|
33
|
+
doc.xpath( '//a[@class="play"]' ).each do |temp|
|
34
|
+
temp = temp.attribute( 'href' ).to_s
|
35
|
+
if( temp.include?( quality ) and temp.include?( '.asx' ) )
|
36
|
+
uri = temp
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
@filename = doc.xpath( '//h1[@class="beitragHeadline"]' ).inner_text + '.wmv'
|
41
|
+
|
42
|
+
doc = Nokogiri::HTML( open( uri ) )
|
43
|
+
# @url = doc.xpath( '//ref' ).attr( 'href' )
|
44
|
+
@url = doc.to_s.match( /(mms.*wmv)/ )[0]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/anstaendig.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
$:.unshift( File.dirname( __FILE__ ) )
|
2
|
+
|
3
|
+
# The Anstaendig module includes an abstract agent class and all agents
|
4
|
+
# implementing this.
|
5
|
+
module Anstaendig
|
6
|
+
VERSION = '0.1.0'
|
7
|
+
end
|
8
|
+
|
9
|
+
Dir.glob( $:.first + '/**/*.rb' ).sort.each do |file|
|
10
|
+
require( file )
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: anstaendig
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- henning mueller
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-05-31 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: anstaendig is a extendable script to rip movie clips from TV station media center sites.
|
23
|
+
email: henning@orgizm.net
|
24
|
+
executables:
|
25
|
+
- anstaendig
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- bin/anstaendig
|
32
|
+
- lib/anstaendig.rb
|
33
|
+
- lib/anstaendig/agents/zdf.rb
|
34
|
+
- lib/anstaendig/agents/ard.rb
|
35
|
+
- lib/anstaendig/agents/3sat.rb
|
36
|
+
- lib/anstaendig/agents/arte.rb
|
37
|
+
- lib/anstaendig/abstractagent.rb
|
38
|
+
- README.rdoc
|
39
|
+
has_rdoc: true
|
40
|
+
homepage:
|
41
|
+
licenses: []
|
42
|
+
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
hash: 3
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 3
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.3.7
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Rip clips from TV station media center sites.
|
73
|
+
test_files: []
|
74
|
+
|