Compare commits
36
Commits
6c5eff65fb
..
v0.2.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
670e28d84f
|
||
|
|
d668817e6c | ||
|
|
aee4986957 | ||
|
|
eed989fd2a | ||
|
|
59aaac408d | ||
|
|
d37f4dbbd1 | ||
|
|
76a174144a | ||
|
|
3da9e2cb1d | ||
|
|
d130761401 | ||
|
|
6572a89085 | ||
|
|
ecb6bb8607 | ||
|
|
11bfe90e3b | ||
|
|
dd76936ee0 | ||
|
|
af55fde4db | ||
|
|
5b06d2229e | ||
|
|
0878d53a55 | ||
|
|
7c15e18071 | ||
|
|
f235d2d0a6 | ||
|
|
e49cf9aa50 | ||
|
|
00d31dda47 | ||
|
|
6af5ed5d06 | ||
|
|
3a9268086b | ||
|
|
efe6943659 | ||
|
|
34c0835d22 | ||
|
|
4395cb42eb | ||
|
|
3cd639eef9 | ||
|
|
c35c296e92 | ||
|
|
b3a0857ddd | ||
|
|
0477940fdf | ||
|
|
f9a39a6f49 | ||
|
|
638d2b6a3d | ||
|
|
1d41e206c0 | ||
|
|
a0377e1f80 | ||
|
|
f4296d8410 | ||
|
|
f28fad2edb | ||
|
|
5cf5c5a597 |
+133
@@ -0,0 +1,133 @@
|
|||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/python
|
||||||
|
|
||||||
|
### Python ###
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
### Python Patch ###
|
||||||
|
.venv/
|
||||||
|
|
||||||
|
### Python.VirtualEnv Stack ###
|
||||||
|
# Virtualenv
|
||||||
|
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
|
||||||
|
[Bb]in
|
||||||
|
[Ii]nclude
|
||||||
|
[Ll]ib
|
||||||
|
[Ll]ib64
|
||||||
|
[Ll]ocal
|
||||||
|
[Ss]cripts
|
||||||
|
pyvenv.cfg
|
||||||
|
pip-selfcheck.json
|
||||||
|
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/python
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
# wiki-jogobot-euroexange
|
# wiki-jogobot-euroexchange
|
||||||
This is a [Pywikibot](https://www.mediawiki.org/wiki/Manual:Pywikibot) based [Wikipedia Bot](https://de.wikipedia.org/wiki/Wikipedia:Bots)
|
This is a [Pywikibot](https://www.mediawiki.org/wiki/Manual:Pywikibot) based [Wikipedia Bot](https://commons.wikimedia.org/wiki/Commons:Bots)
|
||||||
of [User:JogoBot](https://de.wikipedia.org/wiki/Benutzer:JogoBot) on the
|
of [User:JogoBot](https://commons.wikimedia.org/wiki/User:JogoBot) on
|
||||||
[German Wikipedia](https://de.wikipedia.org/wiki/Wikipedia:Hauptseite).
|
[Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
* Python 3.4+ (at least it is only tested with those)
|
* Python 3.4+ (at least it is only tested with those)
|
||||||
@@ -12,17 +10,32 @@ of [User:JogoBot](https://de.wikipedia.org/wiki/Benutzer:JogoBot) on the
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
```
|
```
|
||||||
python euroexange.py
|
python euroexchange.py
|
||||||
```
|
```
|
||||||
|
|
||||||
## Versions
|
## Versions
|
||||||
*
|
* 0.1
|
||||||
|
- First stable release to be run on wmflabs
|
||||||
|
- Download recent sourcefile, generate images based on json job list and upload them
|
||||||
|
|
||||||
|
* 0.1.1
|
||||||
|
- Bugfix: only update image if update period is reached
|
||||||
|
|
||||||
|
* 0.2
|
||||||
|
- Checks gnuplot exitcode and only upload chart if successfull created
|
||||||
|
- Update gnuplot script on commons file description page
|
||||||
|
|
||||||
|
* 0.2.1
|
||||||
|
- Compatibility issue with recent pywikibot fixed
|
||||||
|
|
||||||
|
* 0.2.2
|
||||||
|
- Compatibility issue with recent pywikibot fixed
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
[jogobot-euroexange Issues](https://git.golderweb.de/wiki/jogobot-euroexange/issues)
|
[jogobot-euroexchange Issues](https://git.golderweb.de/wiki/jogobot-euroexchange/issues)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
GPLv3+
|
GPLv3+
|
||||||
|
|
||||||
## Author Information
|
## Author Information
|
||||||
Copyright 2018 Jonathan Golder <jonathan@golderweb.de>
|
Copyright 2022 Jonathan Golder <jonathan@golderweb.de>
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# config.py
|
||||||
|
#
|
||||||
|
# Copyright 2018 Jonathan Golder <jonathan@golderweb.de>
|
||||||
|
#
|
||||||
|
# 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 2 of the License, or
|
||||||
|
# (at your option) 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, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
# MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Loads configuration of EuroExchangeBot
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import jogobot
|
||||||
|
|
||||||
|
|
||||||
|
class Config():
|
||||||
|
"""
|
||||||
|
Configuration container for EuroExchangeBot
|
||||||
|
"""
|
||||||
|
|
||||||
|
base_dir = os.path.expanduser(jogobot.config["euroexchange"]["base_dir"])
|
||||||
|
working_dir = os.path.join( base_dir, "working_dir" )
|
||||||
|
gnuplot_script_dir = os.path.join(base_dir, "gnuplot_scripts")
|
||||||
|
gnuplot = jogobot.config["euroexchange"]["gnuplot_bin"]
|
||||||
|
data_source = jogobot.config["euroexchange"]["data_source"]
|
||||||
|
zip_file = jogobot.config["euroexchange"]["data_zip_filename"]
|
||||||
|
csv_file = jogobot.config["euroexchange"]["data_csv_filename"]
|
||||||
|
upload_comment = jogobot.config["euroexchange"]["upload_comment"]
|
||||||
|
gnuplot_script_comment = jogobot.config["euroexchange"]["gnuplot_script_comment"]
|
||||||
|
gnuplot_script_help = jogobot.config["euroexchange"]["gnuplot_script_help"]
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# descpage.py
|
||||||
|
#
|
||||||
|
# Copyright 2018 Jonathan Golder <jonathan@golderweb.de>
|
||||||
|
#
|
||||||
|
# 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 2 of the License, or
|
||||||
|
# (at your option) 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, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
# MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import pywikibot
|
||||||
|
import mwparserfromhell as mwparser
|
||||||
|
|
||||||
|
from config import Config
|
||||||
|
|
||||||
|
class DescPageBot(pywikibot.bot.Bot):
|
||||||
|
"""
|
||||||
|
Updates file description page with EuroExchangeBot related content
|
||||||
|
"""
|
||||||
|
|
||||||
|
def treat_job( self, job ):
|
||||||
|
"""
|
||||||
|
Handles work on file description page for given job
|
||||||
|
|
||||||
|
@param job Job to work on
|
||||||
|
@type EuroExchangeBotJob
|
||||||
|
"""
|
||||||
|
# Store job
|
||||||
|
self.job = job
|
||||||
|
# Store file page object
|
||||||
|
self.current_page = job.filepage
|
||||||
|
|
||||||
|
# Parse filepage
|
||||||
|
self.parse_page()
|
||||||
|
|
||||||
|
# Update gnuplot script
|
||||||
|
self.update_gnuplot_script()
|
||||||
|
|
||||||
|
# Update wiki page
|
||||||
|
self.update_page()
|
||||||
|
|
||||||
|
def load_gnuplot_script(self):
|
||||||
|
"""
|
||||||
|
Load the gnuplot script for current job
|
||||||
|
|
||||||
|
@return Gnuplot script content
|
||||||
|
@rtype str
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open( os.path.join(
|
||||||
|
Config.gnuplot_script_dir, self.job.script + ".plt" ), "r") as fd:
|
||||||
|
return fd.read()
|
||||||
|
|
||||||
|
def prepare_gnuplot_script(self):
|
||||||
|
"""
|
||||||
|
Prepare gnuplot script code for publishing on image description page
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Load gnuplot script
|
||||||
|
gnuplot_script = self.load_gnuplot_script()
|
||||||
|
|
||||||
|
# Strip leadig and trailing whitespace
|
||||||
|
gnuplot_script = gnuplot_script.strip(" \n")
|
||||||
|
|
||||||
|
# Replace
|
||||||
|
gnuplot_script = gnuplot_script.\
|
||||||
|
replace( "system(\"echo $INFILE\")",
|
||||||
|
"'{}'".format( os.path.basename( Config.csv_file ) ) ).\
|
||||||
|
replace( "system(\"echo $OUTFILE\")",
|
||||||
|
"'{}'".format (os.path.basename( self.job.image ) ) )
|
||||||
|
|
||||||
|
# Locate first empty line
|
||||||
|
m = re.search(r"^\s*$", gnuplot_script, re.MULTILINE)
|
||||||
|
if m:
|
||||||
|
# Insert help lines
|
||||||
|
gnuplot_script = gnuplot_script[:m.end()] +\
|
||||||
|
Config.gnuplot_script_help + gnuplot_script[m.end():]
|
||||||
|
|
||||||
|
return gnuplot_script
|
||||||
|
|
||||||
|
def parse_page(self):
|
||||||
|
"""
|
||||||
|
Load current page content and parse with mwparser
|
||||||
|
"""
|
||||||
|
self.current_page.wikicode = mwparser.parse(self.current_page.text)
|
||||||
|
|
||||||
|
def update_gnuplot_script(self):
|
||||||
|
"""
|
||||||
|
Update the gnuplot script embedded in page
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Get source tag with gnuplot script
|
||||||
|
gnuplot_script = next(
|
||||||
|
self.current_page.wikicode.ifilter_tags(
|
||||||
|
matches="<source lang=\"gnuplot\">" ) )
|
||||||
|
|
||||||
|
# Replace script
|
||||||
|
gnuplot_script.contents = "\n" + self.prepare_gnuplot_script() + "\n"
|
||||||
|
|
||||||
|
def update_page(self):
|
||||||
|
"""
|
||||||
|
Put updated content to wiki
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Convert wikicode back to str
|
||||||
|
new_text = str(self.current_page.wikicode)
|
||||||
|
|
||||||
|
# Save new text
|
||||||
|
self.userPut( self.current_page,
|
||||||
|
self.current_page.text,
|
||||||
|
new_text,
|
||||||
|
summary=Config.gnuplot_script_comment )
|
||||||
@@ -29,13 +29,16 @@ import hashlib
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
import pywikibot
|
import pywikibot
|
||||||
|
import pywikibot.specialbots
|
||||||
|
|
||||||
import jogobot
|
import jogobot
|
||||||
|
|
||||||
|
from config import Config
|
||||||
|
from descpage import DescPageBot
|
||||||
|
|
||||||
class EuroExangeBotJob():
|
class EuroExchangeBotJob():
|
||||||
"""
|
"""
|
||||||
Used for EuroExangeBot job queue
|
Used for EuroExchangeBot job queue
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__( self, **kwargs ):
|
def __init__( self, **kwargs ):
|
||||||
@@ -50,24 +53,17 @@ class EuroExangeBotJob():
|
|||||||
self.image = "TEST_{}".format(self.image)
|
self.image = "TEST_{}".format(self.image)
|
||||||
|
|
||||||
|
|
||||||
class EuroExangeBot( pywikibot.bot.BaseBot ):
|
class EuroExchangeBot( pywikibot.bot.BaseBot ):
|
||||||
|
|
||||||
base_dir = os.path.dirname(os.path.realpath(__file__)) + "/.."
|
|
||||||
working_dir = os.path.dirname(os.path.realpath(__file__)) + "/../wdir"
|
|
||||||
gnuplot_script_dir = os.path.dirname(os.path.realpath(__file__)) + \
|
|
||||||
"/../gnuplot_scripts"
|
|
||||||
gnuplot = "/usr/bin/gnuplot"
|
|
||||||
data_source = "http://www.ecb.int/stats/eurofxref/eurofxref-hist.zip"
|
|
||||||
zip_file = "eurofxref-hist.zip"
|
|
||||||
csv_file = "eurofxref-hist.csv"
|
|
||||||
upload_comment = "Bot: ([[User:Jogobot/Euroexange|euroexange]]) update chart"
|
|
||||||
|
|
||||||
def __init__( self, genFactory, **kwargs ):
|
def __init__( self, genFactory, **kwargs ):
|
||||||
|
|
||||||
# Init working directory
|
# Init working directory
|
||||||
self.init_wdir()
|
self.init_wdir()
|
||||||
|
|
||||||
super().__init__(*kwargs)
|
# Prepare DescPage editing bot
|
||||||
|
self.descpagebot = DescPageBot( **kwargs )
|
||||||
|
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
@@ -85,7 +81,7 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
#Normalize working dir
|
#Normalize working dir
|
||||||
self.wdir = os.path.realpath(type(self).working_dir)
|
self.wdir = os.path.realpath(Config.working_dir)
|
||||||
|
|
||||||
if os.path.exists(self.wdir):
|
if os.path.exists(self.wdir):
|
||||||
|
|
||||||
@@ -108,7 +104,7 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Check if zip file exists
|
# Check if zip file exists
|
||||||
if os.path.exists( os.path.join(self.wdir, type(self).zip_file) ):
|
if os.path.exists( os.path.join(self.wdir, Config.zip_file) ):
|
||||||
|
|
||||||
# If file is outdated, remove data input files
|
# If file is outdated, remove data input files
|
||||||
if not self.is_zip_uptodate():
|
if not self.is_zip_uptodate():
|
||||||
@@ -132,7 +128,7 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
@rtype bool
|
@rtype bool
|
||||||
"""
|
"""
|
||||||
# Get file stat
|
# Get file stat
|
||||||
stat = os.stat( os.path.join(self.wdir, type(self).zip_file) )
|
stat = os.stat( os.path.join(self.wdir, Config.zip_file) )
|
||||||
|
|
||||||
# Get file modification datetime
|
# Get file modification datetime
|
||||||
mdt = datetime.datetime.fromtimestamp( stat.st_mtime )
|
mdt = datetime.datetime.fromtimestamp( stat.st_mtime )
|
||||||
@@ -158,8 +154,8 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
Deletes data input files
|
Deletes data input files
|
||||||
"""
|
"""
|
||||||
|
|
||||||
input_files = ( os.path.join(self.wdir, type(self).zip_file),
|
input_files = ( os.path.join(self.wdir, Config.zip_file),
|
||||||
os.path.join(self.wdir, type(self).csv_file) )
|
os.path.join(self.wdir, Config.csv_file) )
|
||||||
|
|
||||||
for f in input_files:
|
for f in input_files:
|
||||||
os.remove( f )
|
os.remove( f )
|
||||||
@@ -170,9 +166,9 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
Download the zipfile from EZB
|
Download the zipfile from EZB
|
||||||
"""
|
"""
|
||||||
# Download the file and save it locally
|
# Download the file and save it locally
|
||||||
with urllib.request.urlopen(type(self).data_source) as response,\
|
with urllib.request.urlopen(Config.data_source) as response,\
|
||||||
open( os.path.join(self.wdir,
|
open( os.path.join(self.wdir,
|
||||||
type(self).zip_file), 'wb') as out_file:
|
Config.zip_file), 'wb') as out_file:
|
||||||
|
|
||||||
shutil.copyfileobj(response, out_file)
|
shutil.copyfileobj(response, out_file)
|
||||||
|
|
||||||
@@ -182,7 +178,7 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
response.info()["Last-Modified"])
|
response.info()["Last-Modified"])
|
||||||
|
|
||||||
# Set ctime to value from http header
|
# Set ctime to value from http header
|
||||||
os.utime( os.path.join(self.wdir, type(self).zip_file),
|
os.utime( os.path.join(self.wdir, Config.zip_file),
|
||||||
(datetime.datetime.now().timestamp(), mdate.timestamp()) )
|
(datetime.datetime.now().timestamp(), mdate.timestamp()) )
|
||||||
|
|
||||||
# Log
|
# Log
|
||||||
@@ -192,31 +188,31 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
"""
|
"""
|
||||||
Extract csv file from zip archive
|
Extract csv file from zip archive
|
||||||
"""
|
"""
|
||||||
if not os.path.exists( os.path.join(self.wdir, type(self).csv_file) ):
|
if not os.path.exists( os.path.join(self.wdir, Config.csv_file) ):
|
||||||
|
|
||||||
with zipfile.ZipFile(
|
with zipfile.ZipFile(
|
||||||
os.path.join(self.wdir, type(self).zip_file)) as zipobj:
|
os.path.join(self.wdir, Config.zip_file)) as zipobj:
|
||||||
|
|
||||||
zipobj.extract(
|
zipobj.extract(
|
||||||
os.path.basename(
|
os.path.basename(
|
||||||
os.path.join(self.wdir, type(self).csv_file)),
|
os.path.join(self.wdir, Config.csv_file)),
|
||||||
path=self.wdir )
|
path=self.wdir )
|
||||||
|
|
||||||
def load_jobs( self ):
|
def load_jobs( self ):
|
||||||
"""
|
"""
|
||||||
Load jobs from json file
|
Load jobs from json file
|
||||||
|
|
||||||
@returns Generator of EuroExangeBotJob objects
|
@returns Generator of EuroExchangeBotJob objects
|
||||||
@rtype generator
|
@rtype generator
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Load json jobs file
|
# Load json jobs file
|
||||||
with open( os.path.join(self.base_dir, "jobs.json"), "r") as fd:
|
with open( os.path.join(Config.base_dir, "jobs.json"), "r") as fd:
|
||||||
jobs_js = json.load( fd )
|
jobs_js = json.load( fd )
|
||||||
|
|
||||||
# yield each job
|
# yield each job
|
||||||
for job_args in jobs_js:
|
for job_args in jobs_js:
|
||||||
yield EuroExangeBotJob( **job_args )
|
yield EuroExchangeBotJob( **job_args )
|
||||||
|
|
||||||
|
|
||||||
def treat_job( self, job ):
|
def treat_job( self, job ):
|
||||||
@@ -224,7 +220,7 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
Handles working on specific jobs
|
Handles working on specific jobs
|
||||||
|
|
||||||
@param job: Job to work on
|
@param job: Job to work on
|
||||||
@type job: EuroExangeBotJob
|
@type job: EuroExchangeBotJob
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Store reference to current job in Bot obj
|
# Store reference to current job in Bot obj
|
||||||
@@ -237,14 +233,17 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
self.current_job.filepage = pywikibot.page.FilePage(
|
self.current_job.filepage = pywikibot.page.FilePage(
|
||||||
pywikibot.Site(), job.image)
|
pywikibot.Site(), job.image)
|
||||||
|
|
||||||
# Stop if file not jet exists
|
# Skip if file not yet exists
|
||||||
if not self.current_job.filepage.exists():
|
if not self.current_job.filepage.exists():
|
||||||
jogobot.output( "Work on Job {}".format( self.current_job.image),
|
jogobot.output( "Image {} does not exists on wiki, job skipped!".
|
||||||
"ERROR" )
|
format( self.current_job.image), "WARNING" )
|
||||||
raise pywikibot.NoPage( filepage )
|
|
||||||
|
return
|
||||||
|
#~ raise pywikibot.NoPage( self.current_job.filepage )
|
||||||
|
|
||||||
# Check if update is necessary
|
# Check if update is necessary
|
||||||
if self.image_update_needed():
|
if self.image_update_needed():
|
||||||
|
try:
|
||||||
self.call_gnuplot( job )
|
self.call_gnuplot( job )
|
||||||
|
|
||||||
if self.file_changed():
|
if self.file_changed():
|
||||||
@@ -253,11 +252,18 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
jogobot.output( "No upload needed for Job {}.".format(
|
jogobot.output( "No upload needed for Job {}.".format(
|
||||||
self.current_job.image) )
|
self.current_job.image) )
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
jogobot.output( "Subprocess terminated with exit code {}!".
|
||||||
|
format( e.returncode), "ERROR" )
|
||||||
|
|
||||||
# Nothing to do
|
# Nothing to do
|
||||||
else:
|
else:
|
||||||
jogobot.output( "No update needed for Job {}".format(
|
jogobot.output( "No update needed for Job {}".format(
|
||||||
self.current_job.image) )
|
self.current_job.image) )
|
||||||
|
|
||||||
|
# Update file description page
|
||||||
|
self.descpagebot.treat_job( self.current_job )
|
||||||
|
|
||||||
def image_update_needed( self ):
|
def image_update_needed( self ):
|
||||||
"""
|
"""
|
||||||
Checks weather image update intervall is reached.
|
Checks weather image update intervall is reached.
|
||||||
@@ -266,13 +272,11 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
@rtype bool
|
@rtype bool
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Get datetime of last update
|
# Get datetime of last update
|
||||||
last_update = self.current_job.filepage.latest_file_info.timestamp
|
last_update = self.current_job.filepage.latest_file_info.timestamp
|
||||||
|
|
||||||
# Get current time
|
# Get current time
|
||||||
now = pywikibot.Site().getcurrenttime()
|
now = pywikibot.Site().server_time()
|
||||||
|
|
||||||
# Calculate allowed delta (with tolerance)
|
# Calculate allowed delta (with tolerance)
|
||||||
delta = datetime.timedelta( days=self.current_job.freq, hours=-2 )
|
delta = datetime.timedelta( days=self.current_job.freq, hours=-2 )
|
||||||
@@ -286,18 +290,18 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@param job: Job to work on
|
@param job: Job to work on
|
||||||
@type job: EuroExangeBotJob
|
@type job: EuroExchangeBotJob
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cmd = shlex.split ( type(self).gnuplot + " " + os.path.realpath(
|
cmd = shlex.split ( Config.gnuplot + " " + os.path.realpath(
|
||||||
os.path.join( type(self).gnuplot_script_dir,
|
os.path.join( Config.gnuplot_script_dir,
|
||||||
job.script + ".plt" ) ) )
|
job.script + ".plt" ) ) )
|
||||||
|
|
||||||
plt_env = os.environ.copy()
|
plt_env = os.environ.copy()
|
||||||
plt_env["INFILE"] = type(self).csv_file
|
plt_env["INFILE"] = Config.csv_file
|
||||||
plt_env["OUTFILE"] = job.image
|
plt_env["OUTFILE"] = job.image
|
||||||
|
|
||||||
subprocess.call( cmd, cwd=self.wdir, env=plt_env )
|
subprocess.check_call( cmd, cwd=self.wdir, env=plt_env )
|
||||||
|
|
||||||
def file_changed( self ):
|
def file_changed( self ):
|
||||||
"""
|
"""
|
||||||
@@ -323,29 +327,33 @@ class EuroExangeBot( pywikibot.bot.BaseBot ):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@param job: Job to work on
|
@param job: Job to work on
|
||||||
@type job: EuroExangeBotJob
|
@type job: EuroExchangeBotJob
|
||||||
"""
|
"""
|
||||||
|
|
||||||
comment = type(self).upload_comment
|
comment = Config.upload_comment
|
||||||
|
|
||||||
filename = job.image
|
filename = job.image
|
||||||
filepath = os.path.join(self.wdir, job.image)
|
filepath = [ os.path.join(self.wdir, job.image) ]
|
||||||
keepFilename=True #set to True to skip double-checking/editing destination filename
|
keepFilename = True #set to True to skip double-checking/editing destination filename
|
||||||
verifyDescription=True #set to False to skip double-checking/editing description => change to bot-mode
|
verifyDescription = True #set to False to skip double-checking/editing description => change to bot-mode
|
||||||
ignoreWarning=False #set to True to skip warnings, Upload even if another file would be overwritten or another mistake would be risked
|
ignoreWarning = [ "exists", "duplicate", ] #set to True to skip warnings, Upload even if another file would be overwritten or another mistake would be risked
|
||||||
targetSite = pywikibot.Site()
|
targetSite = pywikibot.Site()
|
||||||
|
always = self.opt.always
|
||||||
|
aborts = True if self.opt.always else list()
|
||||||
|
|
||||||
bot = pywikibot.specialbots.UploadRobot(
|
bot = pywikibot.specialbots.UploadRobot(
|
||||||
filepath,
|
filepath,
|
||||||
description=comment,
|
description=comment,
|
||||||
useFilename=filename,
|
use_filename=filename,
|
||||||
keepFilename=keepFilename,
|
keep_filename=keepFilename,
|
||||||
verifyDescription=verifyDescription,
|
verify_description=verifyDescription,
|
||||||
ignoreWarning=ignoreWarning,
|
ignore_warning=ignoreWarning,
|
||||||
targetSite = targetSite
|
target_site = targetSite,
|
||||||
|
always=always,
|
||||||
|
aborts=aborts,
|
||||||
)
|
)
|
||||||
|
|
||||||
bot.upload_image(debug=True)
|
bot.run()
|
||||||
|
|
||||||
def main(*args):
|
def main(*args):
|
||||||
"""
|
"""
|
||||||
@@ -377,7 +385,7 @@ def main(*args):
|
|||||||
local_args, None )
|
local_args, None )
|
||||||
|
|
||||||
# Init Bot
|
# Init Bot
|
||||||
bot = jogobot.bot.init_bot( task_slug, None, EuroExangeBot, genFactory)
|
bot = jogobot.bot.init_bot( task_slug, None, EuroExchangeBot, genFactory, **subtask_args)
|
||||||
|
|
||||||
# Run bot
|
# Run bot
|
||||||
jogobot.bot.run_bot( task_slug, None, bot )
|
jogobot.bot.run_bot( task_slug, None, bot )
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
# based on code of [[User:Gorgo]]/[[:c:File:Euro exchange rate to TRY.svg]]
|
|
||||||
|
|
||||||
# gnuplot script for plotting eurofxref-hist.csv as obtained from
|
|
||||||
# http://www.ecb.int/stats/exchange/eurofxref/html/index.en.html
|
|
||||||
|
|
||||||
infile=system("echo $INFILE")
|
|
||||||
outfile=system("echo $OUTFILE")
|
|
||||||
|
|
||||||
# Start und Ende ermitteln (z.Zt. nur für Consolenausagabe)
|
|
||||||
stats infile every ::1 u (strptime("%Y-%m-%d",strcol(1))) nooutput
|
|
||||||
print ' -----Stats-(Timestamp)----'
|
|
||||||
print ' Start: ', strftime("%d. %B %Y",STATS_min)
|
|
||||||
print ' Ende: ', strftime("%d. %B %Y",STATS_max)
|
|
||||||
print ' --------------------------'
|
|
||||||
set label 'last update: ' . strftime("%Y-%m-%d",STATS_max) at graph 0.05, graph 0.9
|
|
||||||
|
|
||||||
|
|
||||||
#input
|
|
||||||
set timefmt "%Y-%m-%d"
|
|
||||||
set datafile missing 'N/A'
|
|
||||||
set datafile separator ','
|
|
||||||
|
|
||||||
#output
|
|
||||||
set key bottom right
|
|
||||||
set style data lines
|
|
||||||
set border 3 # Rahmen unten (Bit 1) und links (+ Bit 2)
|
|
||||||
unset grid # Gitterlinien verwenden
|
|
||||||
# Gitterlinienen per Hand setzen falls gewünscht
|
|
||||||
set style line 1 linetype rgb '#696969' linewidth 0.5 dashtype 0 # Def. Major-grid
|
|
||||||
set style line 2 linetype rgb '#C9C9C9' linewidth 0.5 dashtype 3 # def. Minor-grid
|
|
||||||
#set grid xtics mxtics # eventuell noxtics und nomxtics
|
|
||||||
set grid x2tics
|
|
||||||
set grid ytics mytics # eventuell noytics und nomytics
|
|
||||||
set grid back # Gitter im Hintergrund
|
|
||||||
set grid linestyle 1, linestyle 2 # Setzen des linestyle für Major u. Minor
|
|
||||||
|
|
||||||
# die Kalenderwochen-Markierung machen wir über x2 !!!
|
|
||||||
set xdata time
|
|
||||||
set x2data time
|
|
||||||
set format x '1. %b'
|
|
||||||
set xtics rotate by +15 center offset 0,-0.5
|
|
||||||
set format x2 ''
|
|
||||||
set xrange ['2018-01-01':'2019-01-01']
|
|
||||||
set x2range ['2018-01-01':'2019-01-01']
|
|
||||||
set x2tics '2018-01-01', 60 * 60 * 24 * 7
|
|
||||||
set x2tic scale 0
|
|
||||||
set xtics nomirror
|
|
||||||
unset mxtics
|
|
||||||
set xlabel '2018'
|
|
||||||
|
|
||||||
|
|
||||||
set ylabel 'TRY'
|
|
||||||
# set y2label 'TRY'
|
|
||||||
set format y '%.0f'
|
|
||||||
# set format y2 '%.0f'
|
|
||||||
|
|
||||||
set ytics 1
|
|
||||||
set mytics 5
|
|
||||||
set ytics nomirror
|
|
||||||
|
|
||||||
# Zebramuster
|
|
||||||
set style rect fillcolor lt -1 fillstyle solid 0.06 noborder
|
|
||||||
do for [i=1:12:2] {
|
|
||||||
marker_start=sprintf("2018-%1.2d-01",i)
|
|
||||||
marker_stop =sprintf("2018-%1.2d-01",i+1)
|
|
||||||
print 'setze grauen Marker: ' . marker_start . "-" . marker_stop
|
|
||||||
set object rectangle from marker_start,graph 0 to marker_stop, graph 1
|
|
||||||
}
|
|
||||||
|
|
||||||
## gnuplot for SVG - gnuplot 4.2 / Ubuntu 8.10
|
|
||||||
set term svg size 800,400 font "Arial,16"
|
|
||||||
|
|
||||||
set outp outfile
|
|
||||||
set style line 1 lt rgb 'blue' lw 1
|
|
||||||
|
|
||||||
#available currencies:
|
|
||||||
#first one is $2, second $3 and so on
|
|
||||||
#USD,JPY,BGN,CYP,CZK,DKK,EEK,GBP,HUF,LTL,LVL,MTL,PLN,ROL,RON,SEK,SIT,SKK,CHF,ISK,NOK,HRK,RUB,TRL,TRY,AUD,BRL,CAD,CNY,HKD,IDR,ILS,INR,KRW,MXN,MYR,NZD,PHP,SGD,THB,ZAR
|
|
||||||
|
|
||||||
plot \
|
|
||||||
infile \
|
|
||||||
usi 1:($26) axis x1y1 tit '1 EUR in TRY' lt rgb 'blue' lw 1,\
|
|
||||||
infile \
|
|
||||||
usi 1:($26) axis x1y1 notit w p lc rgb 'black' lt 1 lw 1.5 pt 7 ps 0.1 \
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# jogobot
|
||||||
|
git+https://git.golderweb.de/wiki/jogobot.git#egg=jogobot
|
||||||
Reference in New Issue
Block a user