1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
5 from twisted.news import news, database
6 from twisted.application import strports
7 from twisted.python import usage, log
9 class DBOptions(usage.Options):
11 ['module', None, 'pyPgSQL.PgSQL', "DB-API 2.0 module to use"],
12 ['dbhost', None, 'localhost', "Host where database manager is listening"],
13 ['dbuser', None, 'news', "Username with which to connect to database"],
14 ['database', None, 'news', "Database name to use"],
15 ['schema', None, 'schema.sql', "File to which to write SQL schema initialisation"],
18 ["groups", "g", "groups.list", "File containing group list"],
19 ["servers", "s", "servers.list", "File containing server list"]
22 def postOptions(self):
24 self['groups'] = [g.strip() for g in open(self['groups']).readlines() if not g.startswith('#')]
25 self['servers'] = [s.strip() for s in open(self['servers']).readlines() if not s.startswith('#')]
28 __import__(self['module'])
30 log.msg("Warning: Cannot import %s" % (self['module'],))
32 f = open(self['schema'], 'w')
34 database.NewsStorageAugmentation.schema + '\n' +
35 database.makeGroupSQL(self['groups']) + '\n' +
36 database.makeOverviewSQL()
41 'host': self['dbhost'], 'user': self['dbuser'],
42 'database': self['database'], 'dbapiName': self['module']
44 self.db = database.NewsStorageAugmentation(info)
47 class PickleOptions(usage.Options):
49 ['file', None, 'news.pickle', "File to which to save pickle"],
52 ["groups", "g", "groups.list", "File containing group list"],
53 ["servers", "s", "servers.list", "File containing server list"],
54 ["moderators", "m", "moderators.list",
55 "File containing moderators list"],
60 def postOptions(self):
62 filename = self['file']
63 self['groups'] = [g.strip() for g in open(self['groups']).readlines()
64 if not g.startswith('#')]
65 self['servers'] = [s.strip() for s in open(self['servers']).readlines()
66 if not s.startswith('#')]
67 self['moderators'] = [s.split()
68 for s in open(self['moderators']).readlines()
69 if not s.startswith('#')]
70 self.db = database.PickleStorage(filename, self['groups'],
74 class Options(usage.Options):
75 synopsis = "[options]"
82 ["port", "p", "119", "Listen port"],
83 ["interface", "i", "", "Interface to which to bind"],
84 ["datadir", "d", "news.db", "Root data storage path"],
85 ["mailhost", "m", "localhost", "Host of SMTP server to use"]
87 compData = usage.Completions(
88 optActions={"datadir" : usage.CompleteDirs(),
89 "mailhost" : usage.CompleteHostnames(),
90 "interface" : usage.CompleteNetInterfaces()}
94 usage.Options.__init__(self)
97 self.subscriptions = []
100 def opt_group(self, group):
101 """The name of a newsgroup to carry."""
102 self.groups.append([group, None])
105 def opt_moderator(self, moderator):
106 """The email of the moderator for the most recently passed group."""
107 self.groups[-1][1] = moderator
110 def opt_subscription(self, group):
111 """A newsgroup to list as a recommended subscription."""
112 self.subscriptions.append(group)
115 def opt_server(self, server):
116 """The address of a Usenet server to pass messages to and receive messages from."""
117 self.servers.append(server)
120 def makeService(config):
121 if not len(config.groups):
122 raise usage.UsageError("No newsgroups specified")
124 db = database.NewsShelf(config['mailhost'], config['datadir'])
125 for (g, m) in config.groups:
128 db.addModerator(g, m)
131 for s in config.subscriptions:
133 db.addSubscription(s)
135 if config['interface']:
137 s += ':interface='+config['interface']
138 return strports.service(s, news.UsenetServerFactory(db, config.servers))