| @@ -14,6 +14,7 @@ Dependencies | |||||
| * [mako](http://www.makotemplates.org/) >= 0.7.2 | * [mako](http://www.makotemplates.org/) >= 0.7.2 | ||||
| * [mwparserfromhell](https://github.com/earwig/mwparserfromhell) >= 0.3 | * [mwparserfromhell](https://github.com/earwig/mwparserfromhell) >= 0.3 | ||||
| * [oursql](http://packages.python.org/oursql/) >= 0.9.3.1 | * [oursql](http://packages.python.org/oursql/) >= 0.9.3.1 | ||||
| * [SQLAlchemy](http://sqlalchemy.org/) >= 0.9.6 | |||||
| * [uglifycss](https://github.com/fmarcia/UglifyCSS/) | * [uglifycss](https://github.com/fmarcia/UglifyCSS/) | ||||
| * [uglifyjs](https://github.com/mishoo/UglifyJS/) >= 1.3.3 | * [uglifyjs](https://github.com/mishoo/UglifyJS/) >= 1.3.3 | ||||
| @@ -7,13 +7,13 @@ from logging.handlers import TimedRotatingFileHandler | |||||
| from time import asctime | from time import asctime | ||||
| from traceback import format_exc | from traceback import format_exc | ||||
| from earwigbot.bot import Bot | |||||
| from flask import Flask, g, request | from flask import Flask, g, request | ||||
| from flask.ext.mako import MakoTemplates, render_template, TemplateError | from flask.ext.mako import MakoTemplates, render_template, TemplateError | ||||
| from flup.server.fcgi import WSGIServer | from flup.server.fcgi import WSGIServer | ||||
| from copyvios.checker import do_check | from copyvios.checker import do_check | ||||
| from copyvios.cookies import parse_cookies | from copyvios.cookies import parse_cookies | ||||
| from copyvios.misc import get_bot | |||||
| from copyvios.settings import process_settings | from copyvios.settings import process_settings | ||||
| from copyvios.sites import get_sites | from copyvios.sites import get_sites | ||||
| @@ -25,6 +25,8 @@ app.logger.addHandler(TimedRotatingFileHandler( | |||||
| "logs/app.log", when="D", interval=1, backupCount=7)) | "logs/app.log", when="D", interval=1, backupCount=7)) | ||||
| app.logger.info(u"Flask server started " + asctime()) | app.logger.info(u"Flask server started " + asctime()) | ||||
| bot = Bot(".earwigbot", 100) | |||||
| def catch_errors(func): | def catch_errors(func): | ||||
| @wraps(func) | @wraps(func) | ||||
| def inner(*args, **kwargs): | def inner(*args, **kwargs): | ||||
| @@ -37,9 +39,11 @@ def catch_errors(func): | |||||
| return inner | return inner | ||||
| @app.before_request | @app.before_request | ||||
| def prepare_cookies(): | |||||
| cookie_string = request.environ.get("HTTP_COOKIE") | |||||
| g.cookies = parse_cookies(request.script_root, cookie_string) | |||||
| def prepare_request(): | |||||
| g.bot = bot | |||||
| g.globals_db = g.cache_db = None | |||||
| g.cookies = parse_cookies(request.script_root, | |||||
| request.environ.get("HTTP_COOKIE")) | |||||
| g.new_cookies = [] | g.new_cookies = [] | ||||
| @app.after_request | @app.after_request | ||||
| @@ -54,6 +58,13 @@ def write_access_log(response): | |||||
| app.logger.debug(msg, asctime(), request.path, response.status_code) | app.logger.debug(msg, asctime(), request.path, response.status_code) | ||||
| return response | return response | ||||
| @app.teardown_appcontext | |||||
| def close_databases(error): | |||||
| if g.globals_db: | |||||
| g.globals_db.close() | |||||
| if g.cache_db: | |||||
| g.cache_db.close() | |||||
| @app.route("/") | @app.route("/") | ||||
| @catch_errors | @catch_errors | ||||
| def index(): | def index(): | ||||
| @@ -64,8 +75,7 @@ def index(): | |||||
| @catch_errors | @catch_errors | ||||
| def settings(): | def settings(): | ||||
| status = process_settings() if request.method == "POST" else None | status = process_settings() if request.method == "POST" else None | ||||
| bot = get_bot() | |||||
| langs, projects = get_sites(bot) | |||||
| langs, projects = get_sites() | |||||
| default = bot.wiki.get_site() | default = bot.wiki.get_site() | ||||
| kwargs = {"status": status, "langs": langs, "projects": projects, | kwargs = {"status": status, "langs": langs, "projects": projects, | ||||
| "default_lang": default.lang, "default_project": default.project} | "default_lang": default.lang, "default_project": default.project} | ||||
| @@ -9,10 +9,12 @@ from time import time | |||||
| from earwigbot import exceptions | from earwigbot import exceptions | ||||
| from flask import g | from flask import g | ||||
| from .misc import get_bot, open_sql_connection | |||||
| from .misc import get_globals_db | |||||
| __all__ = ["set_background"] | |||||
| def set_background(selected): | def set_background(selected): | ||||
| conn = open_sql_connection(get_bot(), "globals") | |||||
| conn = get_globals_db() | |||||
| if "CopyviosScreenCache" in g.cookies: | if "CopyviosScreenCache" in g.cookies: | ||||
| cache = g.cookies["CopyviosScreenCache"].value | cache = g.cookies["CopyviosScreenCache"].value | ||||
| try: | try: | ||||
| @@ -94,11 +96,10 @@ def _load_file(site, filename): | |||||
| return filename.replace(" ", "_"), url, descurl, width, height | return filename.replace(" ", "_"), url, descurl, width, height | ||||
| def _get_site(): | def _get_site(): | ||||
| bot = get_bot() | |||||
| try: | try: | ||||
| return bot.wiki.get_site("commonswiki") | |||||
| return g.bot.wiki.get_site("commonswiki") | |||||
| except exceptions.SiteNotFoundError: | except exceptions.SiteNotFoundError: | ||||
| return bot.wiki.add_site(project="wikimedia", lang="commons") | |||||
| return g.bot.wiki.add_site(project="wikimedia", lang="commons") | |||||
| def _build_url(screen, filename, url, imgwidth, imgheight): | def _build_url(screen, filename, url, imgwidth, imgheight): | ||||
| width = screen["width"] | width = screen["width"] | ||||
| @@ -6,9 +6,11 @@ from urlparse import urlparse | |||||
| from earwigbot import exceptions | from earwigbot import exceptions | ||||
| from .misc import get_bot, Query, open_sql_connection | |||||
| from .misc import Query, get_cache_db | |||||
| from .sites import get_site, get_sites | from .sites import get_site, get_sites | ||||
| __all__ = ["do_check"] | |||||
| def do_check(): | def do_check(): | ||||
| query = Query() | query = Query() | ||||
| if query.lang: | if query.lang: | ||||
| @@ -18,8 +20,7 @@ def do_check(): | |||||
| if query.project: | if query.project: | ||||
| query.project = query.project.lower() | query.project = query.project.lower() | ||||
| query.bot = get_bot() | |||||
| query.all_langs, query.all_projects = get_sites(query.bot) | |||||
| query.all_langs, query.all_projects = get_sites() | |||||
| if query.project and query.lang and (query.title or query.oldid): | if query.project and query.lang and (query.title or query.oldid): | ||||
| query.site = get_site(query) | query.site = get_site(query) | ||||
| if query.site: | if query.site: | ||||
| @@ -43,7 +44,7 @@ def _get_results(query): | |||||
| query.result = page.copyvio_compare(query.url) | query.result = page.copyvio_compare(query.url) | ||||
| query.result.cached = False | query.result.cached = False | ||||
| else: | else: | ||||
| conn = open_sql_connection(query.bot, "cache") | |||||
| conn = get_cache_db() | |||||
| if not query.nocache: | if not query.nocache: | ||||
| query.result = _get_cached_results(page, conn) | query.result = _get_cached_results(page, conn) | ||||
| if not query.result: | if not query.result: | ||||
| @@ -6,6 +6,8 @@ from datetime import datetime, timedelta | |||||
| from flask import g | from flask import g | ||||
| __all__ = ["parse_cookies", "set_cookie", "delete_cookie"] | |||||
| class _CookieManager(SimpleCookie): | class _CookieManager(SimpleCookie): | ||||
| MAGIC = "--cpv2" | MAGIC = "--cpv2" | ||||
| @@ -4,6 +4,8 @@ from re import sub, UNICODE | |||||
| from markupsafe import escape | from markupsafe import escape | ||||
| __all__ = ["highlight_delta"] | |||||
| def highlight_delta(context, chain, delta): | def highlight_delta(context, chain, delta): | ||||
| degree = chain.degree - 1 | degree = chain.degree - 1 | ||||
| highlights = [False] * degree | highlights = [False] * degree | ||||
| @@ -3,12 +3,13 @@ | |||||
| from os.path import expanduser | from os.path import expanduser | ||||
| from urlparse import parse_qs | from urlparse import parse_qs | ||||
| from earwigbot.bot import Bot | |||||
| from flask import request | |||||
| from flask import g, request | |||||
| import oursql | import oursql | ||||
| from sqlalchemy.pool import manage | |||||
| _bot = None | |||||
| _connections = {} | |||||
| oursql = manage(oursql) | |||||
| __all__ = ["Query", "get_globals_db", "get_cache_db", "httpsfix", "urlstrip"] | |||||
| class Query(object): | class Query(object): | ||||
| def __init__(self, method="GET"): | def __init__(self, method="GET"): | ||||
| @@ -36,28 +37,22 @@ class Query(object): | |||||
| self.query[key] = value | self.query[key] = value | ||||
| def get_bot(): | |||||
| global _bot | |||||
| if not _bot: | |||||
| _bot = Bot(".earwigbot", 100) # Don't print any logs to the console | |||||
| return _bot | |||||
| def _connect_db(name): | |||||
| args = g.bot.config.wiki["_copyviosSQL"][name] | |||||
| args["read_default_file"] = expanduser("~/.my.cnf") | |||||
| args["autoping"] = True | |||||
| args["autoreconnect"] = True | |||||
| return oursql.connect(**args) | |||||
| def get_globals_db(): | |||||
| if not g.globals_db: | |||||
| g.globals_db = _connect_db("globals") | |||||
| return g.globals_db | |||||
| def open_sql_connection(bot, dbname): | |||||
| if dbname in _connections: | |||||
| return _connections[dbname] | |||||
| conn_args = bot.config.wiki["_copyviosSQL"][dbname] | |||||
| if "read_default_file" not in conn_args and "user" not in conn_args and "passwd" not in conn_args: | |||||
| conn_args["read_default_file"] = expanduser("~/.my.cnf") | |||||
| elif "read_default_file" in conn_args: | |||||
| default_file = expanduser(conn_args["read_default_file"]) | |||||
| conn_args["read_default_file"] = default_file | |||||
| if "autoping" not in conn_args: | |||||
| conn_args["autoping"] = True | |||||
| if "autoreconnect" not in conn_args: | |||||
| conn_args["autoreconnect"] = True | |||||
| conn = oursql.connect(**conn_args) | |||||
| _connections[dbname] = conn | |||||
| return conn | |||||
| def get_cache_db(): | |||||
| if not g.cache_db: | |||||
| g.cache_db = _connect_db("cache") | |||||
| return g.cache_db | |||||
| def httpsfix(context, url): | def httpsfix(context, url): | ||||
| if url.startswith("http://"): | if url.startswith("http://"): | ||||
| @@ -6,6 +6,8 @@ from markupsafe import escape | |||||
| from .cookies import set_cookie, delete_cookie | from .cookies import set_cookie, delete_cookie | ||||
| from .misc import Query | from .misc import Query | ||||
| __all__ = ["process_settings"] | |||||
| def process_settings(): | def process_settings(): | ||||
| query = Query(method="POST") | query = Query(method="POST") | ||||
| if query.action == "set": | if query.action == "set": | ||||
| @@ -4,12 +4,15 @@ from time import time | |||||
| from urlparse import urlparse | from urlparse import urlparse | ||||
| from earwigbot import exceptions | from earwigbot import exceptions | ||||
| from flask import g | |||||
| from .misc import open_sql_connection | |||||
| from .misc import get_globals_db | |||||
| __all__ = ["get_site", "get_sites"] | |||||
| def get_site(query): | def get_site(query): | ||||
| lang, project, name = query.lang, query.project, query.name | lang, project, name = query.lang, query.project, query.name | ||||
| wiki = query.bot.wiki | |||||
| wiki = g.bot.wiki | |||||
| if project not in [proj[0] for proj in query.all_projects]: | if project not in [proj[0] for proj in query.all_projects]: | ||||
| return None | return None | ||||
| if project == "wikimedia" and name: # Special sites: | if project == "wikimedia" and name: # Special sites: | ||||
| @@ -28,9 +31,9 @@ def get_site(query): | |||||
| except (exceptions.APIError, exceptions.LoginError): | except (exceptions.APIError, exceptions.LoginError): | ||||
| return None | return None | ||||
| def get_sites(bot): | |||||
| def get_sites(): | |||||
| max_staleness = 60 * 60 * 24 * 7 | max_staleness = 60 * 60 * 24 * 7 | ||||
| conn = open_sql_connection(bot, "globals") | |||||
| conn = get_globals_db() | |||||
| query1 = "SELECT update_time FROM updates WHERE update_service = ?" | query1 = "SELECT update_time FROM updates WHERE update_service = ?" | ||||
| query2 = "SELECT lang_code, lang_name FROM language" | query2 = "SELECT lang_code, lang_name FROM language" | ||||
| query3 = "SELECT project_code, project_name FROM project" | query3 = "SELECT project_code, project_name FROM project" | ||||
| @@ -41,7 +44,7 @@ def get_sites(bot): | |||||
| except IndexError: | except IndexError: | ||||
| time_since_update = time() | time_since_update = time() | ||||
| if time_since_update > max_staleness: | if time_since_update > max_staleness: | ||||
| _update_sites(bot.wiki.get_site(), cursor) | |||||
| _update_sites(cursor) | |||||
| cursor.execute(query2) | cursor.execute(query2) | ||||
| langs = [] | langs = [] | ||||
| for code, name in cursor.fetchall(): | for code, name in cursor.fetchall(): | ||||
| @@ -52,7 +55,8 @@ def get_sites(bot): | |||||
| projects = cursor.fetchall() | projects = cursor.fetchall() | ||||
| return langs, projects | return langs, projects | ||||
| def _update_sites(site, cursor): | |||||
| def _update_sites(cursor): | |||||
| site = g.bot.wiki.get_site() | |||||
| matrix = site.api_query(action="sitematrix")["sitematrix"] | matrix = site.api_query(action="sitematrix")["sitematrix"] | ||||
| del matrix["count"] | del matrix["count"] | ||||
| languages, projects = set(), set() | languages, projects = set(), set() | ||||
| @@ -30,7 +30,7 @@ | |||||
| <td colspan="3"> | <td colspan="3"> | ||||
| <span class="mono">http://</span> | <span class="mono">http://</span> | ||||
| <select name="lang"> | <select name="lang"> | ||||
| <% selected_lang = query.orig_lang if query.orig_lang else g.cookies["CopyviosDefaultLang"].value if "CopyviosDefaultLang" in g.cookies else query.bot.wiki.get_site().lang %>\ | |||||
| <% selected_lang = query.orig_lang if query.orig_lang else g.cookies["CopyviosDefaultLang"].value if "CopyviosDefaultLang" in g.cookies else g.bot.wiki.get_site().lang %>\ | |||||
| % for code, name in query.all_langs: | % for code, name in query.all_langs: | ||||
| % if code == selected_lang: | % if code == selected_lang: | ||||
| <option value="${code | h}" selected="selected">${name}</option> | <option value="${code | h}" selected="selected">${name}</option> | ||||
| @@ -41,7 +41,7 @@ | |||||
| </select> | </select> | ||||
| <span class="mono">.</span> | <span class="mono">.</span> | ||||
| <select name="project"> | <select name="project"> | ||||
| <% selected_project = query.project if query.project else g.cookies["CopyviosDefaultProject"].value if "CopyviosDefaultProject" in g.cookies else query.bot.wiki.get_site().project %>\ | |||||
| <% selected_project = query.project if query.project else g.cookies["CopyviosDefaultProject"].value if "CopyviosDefaultProject" in g.cookies else g.bot.wiki.get_site().project %>\ | |||||
| % for code, name in query.all_projects: | % for code, name in query.all_projects: | ||||
| % if code == selected_project: | % if code == selected_project: | ||||
| <option value="${code | h}" selected="selected">${name}</option> | <option value="${code | h}" selected="selected">${name}</option> | ||||