Revision: 6645
Author: nicdumz
Date: 2009-04-21 06:39:18 +0000 (Tue, 21 Apr 2009)
Log Message:
-----------
Starting the Bot class:
I just needed the kind of "userPut" I just implemented, instead of writing
yet another version of that function.
There is definitely room for improvement, please go ahead.
Modified Paths:
--------------
branches/rewrite/pywikibot/bot.py
Modified: branches/rewrite/pywikibot/bot.py
===================================================================
--- branches/rewrite/pywikibot/bot.py 2009-04-21 06:33:00 UTC (rev 6644)
+++ branches/rewrite/pywikibot/bot.py 2009-04-21 06:39:18 UTC (rev 6645)
@@ -451,3 +451,79 @@
level=pywikibot.STDOUT)
logging.exception('showHelp:')
pywikibot.output(globalHelp, level=pywikibot.STDOUT)
+
+class Bot(object):
+ """
+ Generic Bot to be subclassed
+ """
+
+ # Bot configuration.
+ # Only the keys of the dict can be passed as init options
+ # The values are the default values
+ # Extend this in subclasses!
+ availableOptions = {
+ 'always': False, # ask for confirmation when putting a page?
+ }
+
+ def __init__(self, **kwargs):
+ """
+ Only accepts options defined in availableOptions
+ """
+ self.setOptions(kwargs)
+
+ def setOptions(self, **kwargs):
+ """
+ Sets the instance options
+ """
+ # contains the options overriden from defaults
+ self.options = {}
+
+ validOptions = set(availableOptions.iterkeys())
+ receivedOptions = set(kwargs.iterkeys())
+
+ for opt in receivedOptions & validOptions:
+ self.options[opt] = kwargs[opt]
+
+ for opt in receivedOptions - validOptions:
+ logging.warning(u'%s is not a valid option. It was ignored' % opt)
+
+ def getOption(self, option):
+ """
+ Get the current value of an option.
+ @param option: key defined in Bot.availableOptions
+ """
+ try:
+ return self.options.get(option, Bot.availableOptions[option])
+ except KeyError:
+ raise pywikibot.Error(u'%s is not a valid bot option.' % option)
+
+ def userPut(self, page, oldtext, newtext):
+ """
+ Print differences, ask user for confirmation,
+ and puts the page if needed.
+
+ Option used:
+ * 'always'
+ """
+ if oldtext == newtext:
+ logging.info(u'No changes were needed on %s' \
+ % page.title(asLink=True))
+ return
+
+ pywikibot.output(u"\n\n>>> \03{lightpurple}%s\03{default} <<<"
+ % page.title())
+ pywikibot.showDiff(oldtext, newtext)
+
+ choice = 'a'
+ if not self.getOption('always'):
+ choice = pywikibot.inputChoice(
+ u'Do you want to accept these changes?',
+ ['Yes', 'No', 'All'],
+ ['y', 'N', 'a'], 'N')
+ if choice == 'a':
+ # Remember the choice
+ self.options['always'] = True
+
+ if choice != 'N':
+ page.put(newtext, async=(choice=='a'))
+
Revision: 6643
Author: russblau
Date: 2009-04-20 17:37:31 +0000 (Mon, 20 Apr 2009)
Log Message:
-----------
Fix bug in previous commit to fix Bug #2716315 (undetected session termination); if session times out while bot is operating, it will ask the user to log in again (not ideal for automated bots, but apparently unavoidable), unless you have a password file on your local machine.
Modified Paths:
--------------
branches/rewrite/pywikibot/data/api.py
branches/rewrite/pywikibot/site.py
Modified: branches/rewrite/pywikibot/data/api.py
===================================================================
--- branches/rewrite/pywikibot/data/api.py 2009-04-20 15:29:45 UTC (rev 6642)
+++ branches/rewrite/pywikibot/data/api.py 2009-04-20 17:37:31 UTC (rev 6643)
@@ -229,9 +229,19 @@
self.site._userinfo.update(result['query']['userinfo'])
else:
self.site._userinfo = result['query']['userinfo']
- if self.site._userinfo['name'] != self.site.user():
+ status = self.site._loginstatus # save previous login status
+ if ( ("error" in result
+ and result["error"]["code"].endswith("limit"))
+ or (status != -1
+ and self.site._userinfo['name']
+ != self.site._username[status])):
# user is no longer logged in (session expired?)
- self.site.login(self.site._username.index(self.site.user()))
+ # reset userinfo, then make user log in again
+ del self.site._userinfo
+ self.site._loginstatus = -1
+ if status == -1:
+ status = 0 # default to non-sysop login
+ self.site.login(status)
# retry the previous query
continue
if "warnings" in result:
Modified: branches/rewrite/pywikibot/site.py
===================================================================
--- branches/rewrite/pywikibot/site.py 2009-04-20 15:29:45 UTC (rev 6642)
+++ branches/rewrite/pywikibot/site.py 2009-04-20 17:37:31 UTC (rev 6643)
@@ -615,6 +615,9 @@
self.sitelock = threading.Lock()
self._msgcache = {}
self.nocapitalize = self.code in self.family.nocapitalize
+ # _loginstatus: -1 means not logged in, 0 means logged in as user,
+ # 1 means logged in as sysop
+ self._loginstatus = -1
return
# ANYTHING BELOW THIS POINT IS NOT YET IMPLEMENTED IN __init__()
@@ -646,20 +649,25 @@
def login(self, sysop=False):
"""Log the user in if not already logged in."""
- if not hasattr(self, "_siteinfo"):
- self._getsiteinfo()
# check whether a login cookie already exists for this user
- if hasattr(self, "_userinfo"):
- if self.userinfo['name'] == self._username[sysop]:
- return
+ if not hasattr(self, "_userinfo"):
+ self.getuserinfo()
+ if self._userinfo['name'] == self._username[sysop]:
+ self._loginstatus = sysop
+ return
if not self.logged_in(sysop):
loginMan = api.LoginManager(site=self, sysop=sysop,
user=self._username[sysop])
if loginMan.login(retry = True):
self._username[sysop] = loginMan.username
+ self._loginstatus = sysop
if hasattr(self, "_userinfo"):
del self._userinfo
self.getuserinfo()
+ else:
+ self._loginstatus = -1 # failure
+ if not hasattr(self, "_siteinfo"):
+ self._getsiteinfo()
forceLogin = login # alias for backward-compatibility