Merge branch '45' to solve bug #45 about sending multiple times the same message to Mastodon
This commit is contained in:
commit
64f33ecfac
5 changed files with 127 additions and 0 deletions
|
@ -52,8 +52,14 @@ class CliParse:
|
|||
help='tweet all RSS items, regardless of cache')
|
||||
parser.add_argument('-l', '--limit', dest='limit', default=10, type=int,
|
||||
help='tweet only LIMIT items (default: %(default)s)')
|
||||
parser.add_argument('-t', '--lock-timeout', dest='locktimeout', default=3600, type=int,
|
||||
help='lock timeout in seconds after which feed2toot can removes the lock itself')
|
||||
parser.add_argument('--cachefile', dest='cachefile',
|
||||
help='location of the cache file (default: %(default)s)')
|
||||
parser.add_argument('--lockfile', dest='lockfile',
|
||||
default=os.path.join(os.getenv('XDG_CONFIG_HOME', '~/.config'),
|
||||
'feed2toot.lock'),
|
||||
help='location of the lock file (default: %(default)s)')
|
||||
parser.add_argument('-n', '--dry-run', dest='dryrun',
|
||||
action='store_true', default=False,
|
||||
help='Do not actually post tweets')
|
||||
|
|
|
@ -31,6 +31,7 @@ import feedparser
|
|||
from feed2toot.confparsers.cache import parsecache
|
||||
from feed2toot.confparsers.hashtaglist import parsehashtaglist
|
||||
from feed2toot.confparsers.feedparser import parsefeedparser
|
||||
from feed2toot.confparsers.lock import parselock
|
||||
from feed2toot.confparsers.media import parsemedia
|
||||
from feed2toot.confparsers.plugins import parseplugins
|
||||
from feed2toot.confparsers.rss.pattern import parsepattern
|
||||
|
@ -69,6 +70,10 @@ class ConfParse:
|
|||
# pattern and patter_case_sensitive format option
|
||||
#################################################
|
||||
options['patterns'], options['patternscasesensitive'] = parsepattern(config)
|
||||
#################################################
|
||||
# lock file options
|
||||
#################################################
|
||||
options['lockfile'], options['locktimeout'] = parselock(self.clioptions.lockfile, self.clioptions.locktimeout, config)
|
||||
###############################
|
||||
# addtags option, default: True
|
||||
###############################
|
||||
|
|
48
feed2toot/confparsers/lock.py
Normal file
48
feed2toot/confparsers/lock.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright © 2015-2019 Carl Chenet <carl.chenet@ohmytux.com>
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/
|
||||
|
||||
# Get values of the lock section
|
||||
'''Get values of the lock section'''
|
||||
|
||||
# standard library imports
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
def parselock(lockfile, locktimeout, config):
|
||||
'''Parse configuration values and get values of the hashtaglist section'''
|
||||
lockfile = lockfile
|
||||
locktimeout = locktimeout
|
||||
section = 'lock'
|
||||
##################
|
||||
# lockfile option
|
||||
##################
|
||||
confoption = 'lock_file'
|
||||
if config.has_section(section):
|
||||
lockfile = config.get(section, confoption)
|
||||
lockfile = os.path.expanduser(lockfile)
|
||||
lockfileparent = os.path.dirname(lockfile)
|
||||
if lockfileparent and not os.path.exists(lockfileparent):
|
||||
sys.exit('The parent directory of the cache file does not exist: {lockfileparent}'.format(lockfileparent=lockfileparent))
|
||||
######################
|
||||
# lock_timeout option
|
||||
######################
|
||||
if config.has_section(section):
|
||||
confoption = 'lock_timeout'
|
||||
if config.has_option(section, confoption):
|
||||
try:
|
||||
locktimeout = int(config.get(section, confoption))
|
||||
except ValueError as err:
|
||||
sys.exit('Error in configuration with the {confoption} parameter in [{section}]: {err}'.format(confoption=confoption, section=section, err=err))
|
||||
return lockfile, locktimeout
|
63
feed2toot/lock.py
Normal file
63
feed2toot/lock.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
# vim:ts=4:sw=4:ft=python:fileencoding=utf-8
|
||||
# Copyright © 2015-2019 Carl Chenet <carl.chenet@ohmytux.com>
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
'''Manage a lock file'''
|
||||
|
||||
# standard libraires imports
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
class LockFile:
|
||||
'''LockFile object'''
|
||||
def __init__(self, lockfile, locktimeout):
|
||||
'''check the lockfile and the locktimeout'''
|
||||
self.lockfile = lockfile
|
||||
ltimeout = datetime.timedelta(seconds=locktimeout)
|
||||
self.lfdateformat = '%Y-%m-%d_%H-%M-%S'
|
||||
# if a lock file exists
|
||||
if os.path.exists(self.lockfile):
|
||||
if os.path.isfile(self.lockfile):
|
||||
with open(self.lockfile, 'r') as lf:
|
||||
lfcontent = lf.read().rstrip()
|
||||
# lfcontent should be a datetime
|
||||
logging.debug('Check if lock file is older than timeout ({timeout} secs)'.format(timeout=locktimeout))
|
||||
locktime = datetime.datetime.strptime(lfcontent, self.lfdateformat)
|
||||
if locktime < (datetime.datetime.now() - ltimeout):
|
||||
# remove the lock file
|
||||
logging.debug('Found an expired lock file')
|
||||
self.release()
|
||||
self.create_lock()
|
||||
else:
|
||||
# quit because another feed2toot process is running
|
||||
logging.debug('Found a valid lock file. Exiting immediately.')
|
||||
sys.exit(0)
|
||||
else:
|
||||
# no lock file. Creating one
|
||||
self.create_lock()
|
||||
|
||||
def create_lock(self):
|
||||
'''Create a lock file'''
|
||||
with open(self.lockfile, 'w') as lf:
|
||||
currentdatestring = datetime.datetime.now().strftime(self.lfdateformat)
|
||||
lf.write(currentdatestring)
|
||||
logging.debug('lockfile {lockfile} created.'.format(lockfile=self.lockfile))
|
||||
|
||||
def release(self):
|
||||
'''Release the lockfile'''
|
||||
os.remove(self.lockfile)
|
||||
logging.debug('Removed lock file.')
|
|
@ -32,6 +32,7 @@ from feed2toot.filterentry import FilterEntry
|
|||
from feed2toot.removeduplicates import RemoveDuplicates
|
||||
from feed2toot.tootpost import TootPost
|
||||
from feed2toot.feedcache import FeedCache
|
||||
from feed2toot.lock import LockFile
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
class Main:
|
||||
|
@ -71,6 +72,8 @@ class Main:
|
|||
tweetformat = conf[2]
|
||||
feeds = conf[3]
|
||||
plugins = conf[4]
|
||||
# check the logfile and logtimeout
|
||||
lockfile = LockFile(options['lockfile'], options['locktimeout'])
|
||||
# create link to the persistent list
|
||||
cache = FeedCache(options)
|
||||
if 'hashtaglist' in options and options['hashtaglist']:
|
||||
|
@ -221,3 +224,5 @@ class Main:
|
|||
print(err)
|
||||
# do not forget to close cache (shelf object)
|
||||
cache.close()
|
||||
# release the lock file
|
||||
lockfile.release()
|
||||
|
|
Loading…
Reference in a new issue