If you only have games of a single limit type (fixed, pot, or no limit), but of more...
[fpdb-dooglus.git] / pyfpdb / ImapFetcher.py
blobba62673e4f3b56272c86108721ab6fb6ff645a46
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
4 #Copyright 2010 Steffen Schaumburg
5 #This program is free software: you can redistribute it and/or modify
6 #it under the terms of the GNU Affero General Public License as published by
7 #the Free Software Foundation, version 3 of the License.
9 #This program is distributed in the hope that it will be useful,
10 #but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 #GNU General Public License for more details.
14 #You should have received a copy of the GNU Affero General Public License
15 #along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #In the "official" distribution you can find the license in agpl-3.0.txt.
18 """This file is to fetch summaries through IMAP and pass them on to the appropriate parser"""
19 #see http://docs.python.org/library/imaplib.html for the python interface
20 #see http://tools.ietf.org/html/rfc2060#section-6.4.4 for IMAP4 search criteria
22 import L10n
23 _ = L10n.get_translation()
25 from imaplib import IMAP4, IMAP4_SSL
26 import sys
27 import codecs
28 import re
30 import Configuration
31 import Database
32 from Exceptions import FpdbParseError
33 import SQL
34 import Options
35 import PokerStarsSummary
36 import FullTiltPokerSummary
39 def splitPokerStarsSummaries(summaryText): #TODO: this needs to go to PSS.py
40 re_SplitTourneys = PokerStarsSummary.PokerStarsSummary.re_SplitTourneys
41 splitSummaries = re.split(re_SplitTourneys, summaryText)
43 if len(splitSummaries) <= 1:
44 print _("DEBUG: re_SplitTourneys isn't matching")
46 return splitSummaries
48 def splitFullTiltSummaries(summaryText):#TODO: this needs to go to FTPS.py
49 re_SplitTourneys = FullTiltPokerSummary.FullTiltPokerSummary.re_SplitTourneys
50 splitSummaries = re.split(re_SplitTourneys, summaryText)
52 if len(splitSummaries) <= 1:
53 print _("DEBUG: re_SplitTourneys isn't matching")
55 return splitSummaries
57 def run(config, db):
58 #print "start of IS.run"
59 server=None
60 #try:
61 #print "useSSL",config.useSsl,"host",config.host
62 if config.useSsl:
63 server = IMAP4_SSL(config.host)
64 else:
65 server = IMAP4(config.host)
66 response = server.login(config.username, config.password) #TODO catch authentication error
67 print _("response to logging in:"),response
68 #print "server.list():",server.list() #prints list of folders
70 response = server.select(config.folder)
71 #print "response to selecting INBOX:",response
72 if response[0]!="OK":
73 raise error #TODO: show error message
75 neededMessages=[]
76 response, searchData = server.search(None, "SUBJECT", "PokerStars Tournament History Request")
77 for messageNumber in searchData[0].split(" "):
78 response, headerData = server.fetch(messageNumber, "(BODY[HEADER.FIELDS (SUBJECT)])")
79 if response!="OK":
80 raise error #TODO: show error message
81 neededMessages.append(("PS", messageNumber))
83 print _("ImapFetcher: Found %s messages to fetch") %(len(neededMessages))
85 if (len(neededMessages)==0):
86 raise error #TODO: show error message
88 email_bodies = []
89 for i, messageData in enumerate(neededMessages, start=1):
90 print "Retrieving message %s" % i
91 response, bodyData = server.fetch(messageData[1], "(UID BODY[TEXT])")
92 bodyData=bodyData[0][1]
93 if response!="OK":
94 raise error #TODO: show error message
95 if messageData[0]=="PS":
96 email_bodies.append(bodyData)
97 #finally:
98 # try:
99 server.close()
100 # finally:
101 # pass
102 server.logout()
103 print _("Completed retrieving IMAP messages, closing server connection")
105 errors = 0
106 if len(email_bodies) > 0:
107 errors = importSummaries(db, config, email_bodies, options = None)
108 else:
109 print _("No Tournament summaries found.")
111 print _("Errors: %s" % errors)
113 def readFile(filename, options):
114 codepage = ["utf8"]
115 whole_file = None
116 if options.hhc == "PokerStars":
117 codepage = PokerStarsSummary.PokerStarsSummary.codepage
118 elif options.hhc == "Full Tilt Poker":
119 codepage = FullTiltPokerSummary.FullTiltPokerSummary.codepage
121 for kodec in codepage:
122 #print "trying", kodec
123 try:
124 in_fh = codecs.open(filename, 'r', kodec)
125 whole_file = in_fh.read()
126 in_fh.close()
127 break
128 except:
129 pass
131 return whole_file
133 def runFake(db, config, options):
134 summaryText = readFile(options.filename, options)
135 importSummaries(db, config,[summaryText], options=options)
137 def importSummaries(db, config, summaries, options = None):
138 # TODO: At this point we should have:
139 # - list of strings to process
140 # - The sitename OR specialised TourneySummary object
141 # Using options is pretty ugly
142 errors = 0
143 for summaryText in summaries:
144 # And we should def be using a 'Split' from the site object
145 if options == None or options.hhc == "PokerStars":
146 summaryTexts=(splitPokerStarsSummaries(summaryText))
147 elif options.hhc == "Full Tilt Poker":
148 summaryTexts=(splitFullTiltSummaries(summaryText))
150 print "Found %s summaries in email" %(len(summaryTexts))
151 for j, summaryText in enumerate(summaryTexts, start=1):
152 try:
153 if options == None or options.hhc == "PokerStars":
154 PokerStarsSummary.PokerStarsSummary(db=db, config=config, siteName=u"PokerStars", summaryText=summaryText, builtFrom = "IMAP")
155 elif options.hhc == "Full Tilt Poker":
156 FullTiltPokerSummary.FullTiltPokerSummary(db=db, config=config, siteName=u"Fulltilt", summaryText=summaryText, builtFrom = "IMAP")
157 except FpdbParseError, e:
158 errors += 1
159 print _("Finished importing %s/%s PS summaries") %(j, len(summaryTexts))
161 return errors
164 def main(argv=None):
165 if argv is None:
166 argv = sys.argv[1:]
168 (options, argv) = Options.fpdb_options()
170 if options.usage == True:
171 #Print usage examples and exit
172 print _("USAGE:")
173 sys.exit(0)
175 if options.hhc == "PokerStarsToFpdb":
176 print _("Need to define a converter")
177 exit(0)
179 # These options should really come from the OptionsParser
180 config = Configuration.Config()
181 db = Database.Database(config)
182 sql = SQL.Sql(db_server = 'sqlite')
183 settings = {}
184 settings.update(config.get_db_parameters())
185 settings.update(config.get_import_parameters())
186 settings.update(config.get_default_paths())
187 db.recreate_tables()
189 runFake(db, config, options)
191 if __name__ == '__main__':
192 sys.exit(main())