130 lines
3.4 KiB
Python
Executable file
130 lines
3.4 KiB
Python
Executable file
#!/usr/bin/python3
|
|
"""Find photos on flickr for Wikipedia articles and contact the photographer."""
|
|
|
|
import collections
|
|
import inspect
|
|
import json
|
|
import sys
|
|
import traceback
|
|
import typing
|
|
from urllib.parse import unquote
|
|
|
|
import flask
|
|
import requests
|
|
import werkzeug
|
|
from werkzeug.debug.tbtools import DebugTraceback
|
|
|
|
app = flask.Flask(__name__)
|
|
app.debug = False
|
|
|
|
enwiki = "en.wikipedia.org/wiki/"
|
|
|
|
|
|
@app.errorhandler(werkzeug.exceptions.InternalServerError)
|
|
def exception_handler(e: werkzeug.exceptions.InternalServerError) -> tuple[str, int]:
|
|
"""Handle exception."""
|
|
exec_type, exc_value, current_traceback = sys.exc_info()
|
|
assert exc_value
|
|
tb = DebugTraceback(exc_value)
|
|
|
|
summary = tb.render_traceback_html(include_title=False)
|
|
exc_lines = "".join(tb._te.format_exception_only())
|
|
|
|
last_frame = list(traceback.walk_tb(current_traceback))[-1][0]
|
|
last_frame_args = inspect.getargs(last_frame.f_code)
|
|
|
|
return (
|
|
flask.render_template(
|
|
"show_error.html",
|
|
plaintext=tb.render_traceback_text(),
|
|
exception=exc_lines,
|
|
exception_type=tb._te.exc_type.__name__,
|
|
summary=summary,
|
|
last_frame=last_frame,
|
|
last_frame_args=last_frame_args,
|
|
),
|
|
500,
|
|
)
|
|
|
|
|
|
@app.route("/")
|
|
def start() -> str:
|
|
"""Start form."""
|
|
wikipedia_url = flask.request.args.get("wikipedia")
|
|
if not wikipedia_url:
|
|
return flask.render_template("combined.html")
|
|
|
|
start = wikipedia_url.find(enwiki) + len(enwiki)
|
|
wiki_part2 = unquote(wikipedia_url[start:])
|
|
|
|
name = wiki_part2
|
|
|
|
if "_(" in name:
|
|
name = name[: name.find("_(")]
|
|
name = name.replace("_", " ")
|
|
|
|
flickr_url = flask.request.args.get("flickr")
|
|
if not flickr_url:
|
|
return flask.render_template(
|
|
"combined.html",
|
|
name=name,
|
|
wikipedia_url=wikipedia_url,
|
|
)
|
|
|
|
wiki_part1 = wikipedia_url[:start]
|
|
|
|
if "/in/" in flickr_url:
|
|
flickr_url = flickr_url[: flickr_url.find("/in/")]
|
|
|
|
flickr_start = "https://flickr.com/photos/"
|
|
|
|
assert flickr_url.startswith(flickr_start)
|
|
flickr_username = flickr_url[
|
|
len(flickr_start) : flickr_url.find("/", len(flickr_start))
|
|
]
|
|
|
|
nsid = flickr_usrename_to_nsid(flickr_username)
|
|
assert nsid
|
|
print(nsid)
|
|
|
|
msg = flask.render_template(
|
|
"message.jinja",
|
|
flickr_url=flickr_url,
|
|
wikipedia_url=wikipedia_url,
|
|
name=name,
|
|
wiki_part1=wiki_part1,
|
|
wiki_part2=wiki_part2,
|
|
)
|
|
|
|
subject = f"Request to use your photo of {name} on Wikipedia"
|
|
|
|
lines = msg.split("\n\n")
|
|
|
|
return flask.render_template(
|
|
"combined.html",
|
|
name=name,
|
|
wikipedia_url=wikipedia_url,
|
|
flickr_url=flickr_url,
|
|
subject=subject,
|
|
lines=lines,
|
|
nsid=nsid,
|
|
)
|
|
|
|
|
|
def get_params(line_iter: collections.abc.Iterable[str]) -> str:
|
|
"""Find and return params from flickr profile page."""
|
|
look_for = 'params: {"isEditingTestimonial":false,'
|
|
return next(line[line.find("{") :] for line in line_iter if look_for in line)
|
|
|
|
|
|
def flickr_usrename_to_nsid(username: str) -> str:
|
|
"""Get NSID from flickr username."""
|
|
url = f"https://www.flickr.com/people/{username}/"
|
|
r = requests.get(url)
|
|
params = json.loads(get_params(r.text.splitlines()))
|
|
return typing.cast(str, params["nsid"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app.run(host="0.0.0.0")
|