newsfire_export 1.1.0-powerpc-darwin
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.
- data/bin/newsfire_export +39 -0
- data/lib/newsfire_export.rb +196 -0
- metadata +51 -0
data/bin/newsfire_export
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# Copyright (c) 2006, Horst Gutmann <zerok@zerokspot.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
8
|
+
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
9
|
+
# * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
10
|
+
#
|
11
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
12
|
+
#
|
13
|
+
# Version:: 1.1.0
|
14
|
+
# Author:: Horst Gutmann, zerok@zerokspot.com
|
15
|
+
# License:: BSD License
|
16
|
+
|
17
|
+
require 'optparse'
|
18
|
+
require 'newsfire_export'
|
19
|
+
|
20
|
+
options={
|
21
|
+
:filter=>false,
|
22
|
+
:origpath=>nil,
|
23
|
+
}
|
24
|
+
filepath = nil
|
25
|
+
OptionParser.new do |opts|
|
26
|
+
opts.banner="Usage: newsfire_export.rb [options]"
|
27
|
+
opts.separator ""
|
28
|
+
opts.separator "Prints your NewsFire's feedlist to STDOUT"
|
29
|
+
opts.separator "Options:"
|
30
|
+
opts.on("-i","--input [F]","Specify the plist file of NewsFire here"){|f| options[:origpath]=f}
|
31
|
+
opts.on("-o","--output [F]","Write OPML to specified file F"){|f| filepath=f}
|
32
|
+
opts.on("-f","--filter","Filter all Feeds and Groups starting with an underscore") {options[:filter]=true}
|
33
|
+
opts.on_tail("-h","--help","Show this message"){puts opts;exit 0}
|
34
|
+
end.parse!
|
35
|
+
if filepath.nil?
|
36
|
+
$stdout.write(NewsFireExport::Feedlist.new(options))
|
37
|
+
else
|
38
|
+
File.open(filepath,"w+"){|output| output.write(NewsFireExport::Feedlist.new(options))}
|
39
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
# Copyright (c) 2006, Horst Gutmann <zerok@zerokspot.com>
|
2
|
+
# All rights reserved.
|
3
|
+
#
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
5
|
+
#
|
6
|
+
# * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
7
|
+
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
8
|
+
# * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
9
|
+
#
|
10
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
11
|
+
#
|
12
|
+
# Version:: 1.1.0
|
13
|
+
# Author:: Horst Gutmann, zerok@zerokspot.com
|
14
|
+
# License:: BSD License
|
15
|
+
|
16
|
+
require 'fileutils'
|
17
|
+
require 'pp'
|
18
|
+
require 'rubygems'
|
19
|
+
require_gem 'plist','>=1.0.0'
|
20
|
+
|
21
|
+
# Extending Patrick May's Plist to support Data and Date.
|
22
|
+
#
|
23
|
+
# These are just dummy classes to prevent the script from raising Exceptions
|
24
|
+
# because Data and Date are used by NewsFire.
|
25
|
+
class Plist
|
26
|
+
class PDate < PTag
|
27
|
+
def to_ruby
|
28
|
+
# m=text.match(/^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z(.*?)$/)
|
29
|
+
# if not m.nil?
|
30
|
+
# Time.gm(m[6],m[5],m[4],m[3],m[2],m[1],nil,nil,nil,nil)
|
31
|
+
# end
|
32
|
+
text # We don't use Date anyway ;)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
class PData < PTag
|
36
|
+
def to_ruby
|
37
|
+
text
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module NewsFireExport
|
43
|
+
class NoNameException < RuntimeError
|
44
|
+
end
|
45
|
+
# Representation of a feed that also holds everything that is needed for the
|
46
|
+
# OPML outline output
|
47
|
+
class Feed
|
48
|
+
attr_reader :name,:htmlurl,:xmlurl,:description
|
49
|
+
def initialize hash,feedlist
|
50
|
+
if hash['address'].nil?
|
51
|
+
pp hash
|
52
|
+
raise "Not a feed"
|
53
|
+
end
|
54
|
+
@feedlist=feedlist
|
55
|
+
@description = hash['comment']
|
56
|
+
@xmlurl=hash['address']
|
57
|
+
@htmlurl=hash['link']
|
58
|
+
@name=hash['name']
|
59
|
+
if @name.nil?
|
60
|
+
raise NoNameException,"#{xmlurl} has no name"
|
61
|
+
@name=@xmlurl
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Generates by default an OPML outline or "" if the feedname starts with
|
66
|
+
# an underscore and filtering is enabled
|
67
|
+
def to_s
|
68
|
+
return "" if @feedlist.filter and @name=~/^_/
|
69
|
+
to_opml
|
70
|
+
end
|
71
|
+
|
72
|
+
# Tries to emulate the xmlUrl->filename conversion done by NewsFire
|
73
|
+
def get_key
|
74
|
+
@xmlurl.gsub(/^http:\/\//,'').gsub(/^www\./,'').gsub(/\//,'-').gsub('?','-')
|
75
|
+
end
|
76
|
+
|
77
|
+
#####
|
78
|
+
protected
|
79
|
+
#####
|
80
|
+
def to_opml
|
81
|
+
"<outline description=\"#{@description}\" text=\"#{@name}\" htmlUrl=\"#{@htmlurl}\" xmlUrl=\"#{@xmlurl}\"/>"
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
class Group
|
86
|
+
@@num_untitled=0
|
87
|
+
attr_reader :feeds,:name
|
88
|
+
attr_writer :feeds
|
89
|
+
def initialize hash,feedlist
|
90
|
+
@name=hash['name']
|
91
|
+
@name="Untitled group #{@@num_untitled+=1}" if @name.nil?
|
92
|
+
@feedlist=feedlist
|
93
|
+
@feeds = Hash.new
|
94
|
+
hash['conditionsArray'].each do |feed|
|
95
|
+
@feeds[feed['friendlyFileName']]=nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
def add_feed feed
|
99
|
+
end
|
100
|
+
def to_s
|
101
|
+
return "" if @feedlist.filter and @name=~/^_/
|
102
|
+
to_opml
|
103
|
+
end
|
104
|
+
|
105
|
+
######
|
106
|
+
protected
|
107
|
+
######
|
108
|
+
def to_opml
|
109
|
+
ret="<outline text=\"#{@name}\">"
|
110
|
+
@feeds.keys.sort{|a,b| @feeds[a].name.upcase<=> @feeds[b].name.upcase}.each{|f| ret<<@feeds[f].to_s}
|
111
|
+
ret<<"</outline>"
|
112
|
+
ret
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Representation of the whole feedlist. Creating a new object of it basically
|
117
|
+
# does everything: It reads the feedlist from NewsFire, converts it into OPML.
|
118
|
+
# All that is left to do is call it's to_s method ;)
|
119
|
+
class Feedlist
|
120
|
+
attr_reader :filter
|
121
|
+
def initialize(options={:origpath=>nil,:filter=>false})
|
122
|
+
origpath = options[:origpath]
|
123
|
+
if origpath.nil?
|
124
|
+
origpath = File.join(ENV['HOME'],'Library','Preferences','org.xlife.NewsFire.plist')
|
125
|
+
end
|
126
|
+
raise "NewsFire config file not found" if not File.exists?(origpath)
|
127
|
+
@origpath=origpath
|
128
|
+
@tmpxmlpath=File.join(ENV['HOME'],".nfe_#{Process.pid}.xml")
|
129
|
+
@list = Array.new
|
130
|
+
@groups = Array.new
|
131
|
+
@feeds = Array.new
|
132
|
+
@grouped_feeds = Hash.new
|
133
|
+
@filter = options[:filter]
|
134
|
+
import_origfile
|
135
|
+
|
136
|
+
@plist['Feeds'].each do |feed|
|
137
|
+
if feed['className']=='Group'
|
138
|
+
@groups<<Group.new(feed,self)
|
139
|
+
else
|
140
|
+
if feed['isGrouped']==0
|
141
|
+
next if feed['address'].nil?
|
142
|
+
@feeds<<Feed.new(feed,self)
|
143
|
+
else
|
144
|
+
f = Feed.new(feed,self)
|
145
|
+
@grouped_feeds[f.get_key]=f
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
@groups.each do |g|
|
150
|
+
g.feeds.keys.each do |k|
|
151
|
+
g.feeds[k]=@grouped_feeds[k]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# to_s dispatcher (currently only OPML supported)
|
157
|
+
def to_s
|
158
|
+
to_opml
|
159
|
+
end
|
160
|
+
|
161
|
+
######
|
162
|
+
protected
|
163
|
+
######
|
164
|
+
|
165
|
+
# to_s->OPML
|
166
|
+
def to_opml
|
167
|
+
ret=<<EOD
|
168
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
169
|
+
<opml version="1.1">
|
170
|
+
EOD
|
171
|
+
ret << "<head><title>NewsFire export</title><dateCreated>#{Time.new}</dateCreated></head><body>"
|
172
|
+
@groups.sort{|a,b| a.name.upcase <=> b.name.upcase}.each{|g| ret << g.to_s}
|
173
|
+
@feeds.sort{ |a,b| a.name.upcase<=>b.name.upcase }.each{|f| ret << f.to_s}
|
174
|
+
ret<< <<-EOD
|
175
|
+
</body>
|
176
|
+
</opml>
|
177
|
+
EOD
|
178
|
+
ret
|
179
|
+
end
|
180
|
+
|
181
|
+
# Converts NewsFire's config file from binary plist to xml plist
|
182
|
+
# and runs the Plist parser on it. After doing this the tmpfile
|
183
|
+
# is deleted
|
184
|
+
def import_origfile
|
185
|
+
FileUtils.cp(@origpath,@tmpxmlpath)
|
186
|
+
system("plutil -convert xml1 #{@tmpxmlpath}")
|
187
|
+
begin
|
188
|
+
@plist = Plist.parse_xml(@tmpxmlpath)
|
189
|
+
rescue Exception => e
|
190
|
+
pp e
|
191
|
+
end
|
192
|
+
FileUtils.rm(@tmpxmlpath)
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: newsfire_export
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.1.0
|
7
|
+
date: 2006-01-27 00:00:00 +01:00
|
8
|
+
summary: Programm for exporting the feedlist of the NewsFire Atom/RSS reader into an OPML file
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: zerok@zerokspot.com
|
12
|
+
homepage: http://zerokspot.com
|
13
|
+
rubyforge_project:
|
14
|
+
description: Programm for exporting the feedlist of the NewsFire Atom/RSS reader into an OPML file
|
15
|
+
autorequire: newsfire_export.rb
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: powerpc-darwin
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- Horst Gutmann
|
31
|
+
files:
|
32
|
+
- bin/newsfire_export
|
33
|
+
- lib/newsfire_export.rb
|
34
|
+
test_files: []
|
35
|
+
rdoc_options: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
executables:
|
38
|
+
- newsfire_export
|
39
|
+
extensions: []
|
40
|
+
requirements: []
|
41
|
+
dependencies:
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: plist
|
44
|
+
version_requirement:
|
45
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
46
|
+
requirements:
|
47
|
+
-
|
48
|
+
- ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 1.0.0
|
51
|
+
version:
|