|
@ -1,7 +1,9 @@ |
|
|
from flask import Flask, render_template, Response |
|
|
from flask import Flask, render_template, Response |
|
|
import requests |
|
|
import requests |
|
|
|
|
|
import re |
|
|
from bs4 import BeautifulSoup |
|
|
from bs4 import BeautifulSoup |
|
|
from datetime import datetime |
|
|
from datetime import datetime |
|
|
|
|
|
from dateutil.relativedelta import relativedelta |
|
|
|
|
|
|
|
|
class WikiApp(Flask): |
|
|
class WikiApp(Flask): |
|
|
|
|
|
|
|
@ -14,12 +16,153 @@ class WikiApp(Flask): |
|
|
# Define routes |
|
|
# Define routes |
|
|
# self.route('/', methods=['GET'])(self.homepage) |
|
|
# self.route('/', methods=['GET'])(self.homepage) |
|
|
self.route('/', methods=['GET'])(self.homepage_new) |
|
|
self.route('/', methods=['GET'])(self.homepage_new) |
|
|
|
|
|
self.route('/newsletter/<string:title>', methods=['GET'])(self.generate_newsletter) |
|
|
self.route('/publications', methods=['GET'])(self.fetch_publications) |
|
|
self.route('/publications', methods=['GET'])(self.fetch_publications) |
|
|
self.route('/meetups', methods=['GET'])(self.fetch_meetups) |
|
|
self.route('/meetups', methods=['GET'])(self.fetch_meetups) |
|
|
self.route('/<string:title>', methods=['GET'])(self.page_content) |
|
|
self.route('/<string:title>', methods=['GET'])(self.page_content) |
|
|
self.route('/favicon.ico')(self.favicon) |
|
|
self.route('/favicon.ico')(self.favicon) |
|
|
self.route('/archive/<string:collection>', methods=['GET'])(self.get_collection) |
|
|
self.route('/archive/<string:collection>', methods=['GET'])(self.get_collection) |
|
|
|
|
|
|
|
|
|
|
|
def generate_newsletter(self, title): |
|
|
|
|
|
content, title, date = self.fetch_page(title) |
|
|
|
|
|
given_date = datetime.strptime(date, "%Y-%m-%d") |
|
|
|
|
|
new_date_opp = given_date + relativedelta(months=2) |
|
|
|
|
|
new_date_events = given_date + relativedelta(weeks=2) |
|
|
|
|
|
opportunites_dict = self.fetch_opportunities(given_date.date(), new_date_opp.date()) |
|
|
|
|
|
events_dict = self.fetch_events(given_date.date(), new_date_events.date()) |
|
|
|
|
|
return render_template('newsletter.html', nav_elements=self.get_nav_menu(), content=content, title=title, events=events_dict, opportunities=opportunites_dict) |
|
|
|
|
|
|
|
|
|
|
|
def fetch_opportunities(self, pub_date, future_date): |
|
|
|
|
|
all_opportunities = self.fetch_all_opportunities(pub_date, future_date) |
|
|
|
|
|
if not all_opportunities: |
|
|
|
|
|
return {} |
|
|
|
|
|
else: |
|
|
|
|
|
titles = '' |
|
|
|
|
|
for value in all_opportunities.values(): |
|
|
|
|
|
if isinstance(value, list): |
|
|
|
|
|
for entry in value: |
|
|
|
|
|
titles += entry['pagetitle'] + '|' |
|
|
|
|
|
|
|
|
|
|
|
titles = titles[:-1] |
|
|
|
|
|
resp = requests.get(self.MEDIAWIKI_BASE_URL + self.BASE_API, params={ |
|
|
|
|
|
'action': 'query', |
|
|
|
|
|
'titles': titles, |
|
|
|
|
|
'format': 'json', |
|
|
|
|
|
'prop': 'extracts', |
|
|
|
|
|
'exlimit': '20', |
|
|
|
|
|
'explaintext': 'true', |
|
|
|
|
|
'exintro': 'true' |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
data = resp.json() |
|
|
|
|
|
opp_data = data.get('query', {}).get('pages', {}) |
|
|
|
|
|
|
|
|
|
|
|
for residency_entry in all_opportunities.values(): |
|
|
|
|
|
for open_call_entry in opp_data.values(): |
|
|
|
|
|
if residency_entry[0]['pagetitle'] == open_call_entry['title']: |
|
|
|
|
|
residency_entry[0]['text'] = open_call_entry['extract'] |
|
|
|
|
|
|
|
|
|
|
|
sorted_data = {key: sorted(value, key=lambda x: x['deadline'], reverse=True) for key, value in all_opportunities.items()} |
|
|
|
|
|
return sorted_data |
|
|
|
|
|
|
|
|
|
|
|
def fetch_all_opportunities(self, pub_date, future_date): |
|
|
|
|
|
opp_page_list = {} |
|
|
|
|
|
categories = ['Opportunities'] |
|
|
|
|
|
for category in categories: |
|
|
|
|
|
response = requests.get(self.MEDIAWIKI_BASE_URL + self.BASE_API, params={'action': 'ask', 'query': '[[Concept:'+category+']] [[Opportunities:Deadline::<=' + future_date.strftime("%Y-%m-%d") + ']] [[Opportunities:Deadline::>='+ pub_date.strftime("%Y-%m-%d") + ']] |?Opportunities:Deadline|?Opportunities:Name|?Opportunities:Location|?Opportunities:Organiser/s|?Opportunities:Type|?Opportunities:Source', 'format': 'json', 'formatversion': '2'}) |
|
|
|
|
|
data = response.json() |
|
|
|
|
|
|
|
|
|
|
|
opp_info = {} |
|
|
|
|
|
if not data['query']['results']: |
|
|
|
|
|
return {} |
|
|
|
|
|
else: |
|
|
|
|
|
for page_title, page_data in data['query']['results'].items(): |
|
|
|
|
|
if 'printouts' in page_data and 'Opportunities:Deadline' in page_data['printouts']: |
|
|
|
|
|
type = page_data['printouts']['Opportunities:Type'][0] |
|
|
|
|
|
name = page_data['printouts']['Opportunities:Name'][0] |
|
|
|
|
|
deadline = page_data['printouts']['Opportunities:Deadline'][0]['raw'] |
|
|
|
|
|
deadline = deadline[2:] |
|
|
|
|
|
lol = datetime.strptime(deadline, "%Y/%m/%d") |
|
|
|
|
|
formatted_deadline = lol.strftime("%d-%m-%Y") |
|
|
|
|
|
location = page_data['printouts']['Opportunities:Location'][0] |
|
|
|
|
|
source = page_data['printouts']['Opportunities:Source'][0] |
|
|
|
|
|
org = page_data['printouts']['Opportunities:Organiser/s'][0]['fulltext'] |
|
|
|
|
|
|
|
|
|
|
|
opp_info = {'pagetitle': page_title, 'name': name, 'deadline': formatted_deadline, 'location': location, 'source' : source, 'org': org, 'text': ''} |
|
|
|
|
|
|
|
|
|
|
|
if type not in opp_page_list: |
|
|
|
|
|
opp_page_list[type] = [] |
|
|
|
|
|
|
|
|
|
|
|
opp_page_list[type].append(opp_info) |
|
|
|
|
|
|
|
|
|
|
|
return opp_page_list |
|
|
|
|
|
|
|
|
|
|
|
def fetch_events(self, pub_date, future_date): |
|
|
|
|
|
all_events = self.fetch_all_events(pub_date, future_date) |
|
|
|
|
|
if not all_events: |
|
|
|
|
|
return {} |
|
|
|
|
|
else: |
|
|
|
|
|
titles = '' |
|
|
|
|
|
|
|
|
|
|
|
for value in all_events.values(): |
|
|
|
|
|
if isinstance(value, list): |
|
|
|
|
|
for entry in value: |
|
|
|
|
|
titles += entry['pagetitle'] + '|' |
|
|
|
|
|
|
|
|
|
|
|
titles = titles[:-1] |
|
|
|
|
|
resp = requests.get(self.MEDIAWIKI_BASE_URL + self.BASE_API, params={ |
|
|
|
|
|
'action': 'query', |
|
|
|
|
|
'titles': titles, |
|
|
|
|
|
'format': 'json', |
|
|
|
|
|
'prop': 'extracts', |
|
|
|
|
|
'exlimit': '20', |
|
|
|
|
|
'explaintext': 'true', |
|
|
|
|
|
'exintro': 'true' |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
data = resp.json() |
|
|
|
|
|
opp_data = data.get('query', {}).get('pages', {}) |
|
|
|
|
|
|
|
|
|
|
|
for residency_entry in all_events.values(): |
|
|
|
|
|
for open_call_entry in opp_data.values(): |
|
|
|
|
|
if residency_entry[0]['pagetitle'] == open_call_entry['title']: |
|
|
|
|
|
residency_entry[0]['text'] = open_call_entry['extract'] |
|
|
|
|
|
|
|
|
|
|
|
sorted_data = {key: sorted(value, key=lambda x: x['deadline'], reverse=False) for key, value in all_events.items()} |
|
|
|
|
|
return sorted_data |
|
|
|
|
|
|
|
|
|
|
|
def fetch_all_events(self, pub_date, future_date): |
|
|
|
|
|
opp_page_list = {} |
|
|
|
|
|
categories = ['Events'] |
|
|
|
|
|
for category in categories: |
|
|
|
|
|
response = requests.get(self.MEDIAWIKI_BASE_URL + self.BASE_API, params={'action': 'ask', 'query': '[[Concept:'+category+']] [[Event:Date::<=' + future_date.strftime("%Y-%m-%d") + ']] [[Event:Date::>='+ pub_date.strftime("%Y-%m-%d") + ']] |?Event:Date|?Event:Name|?Event:Location|?Event:Organiser/s|?Event:Source', 'format': 'json', 'formatversion': '2'}) |
|
|
|
|
|
data = response.json() |
|
|
|
|
|
|
|
|
|
|
|
opp_info = {} |
|
|
|
|
|
if not data['query']['results']: |
|
|
|
|
|
return {} |
|
|
|
|
|
else: |
|
|
|
|
|
for page_title, page_data in data['query']['results'].items(): |
|
|
|
|
|
if 'printouts' in page_data and 'Event:Date' in page_data['printouts']: |
|
|
|
|
|
type = 'Events' |
|
|
|
|
|
name = page_data['printouts']['Event:Name'][0] |
|
|
|
|
|
deadline = page_data['printouts']['Event:Date'][0]['raw'] |
|
|
|
|
|
deadline = deadline[2:] |
|
|
|
|
|
lol = datetime.strptime(deadline, "%Y/%m/%d") |
|
|
|
|
|
formatted_deadline = lol.strftime("%d-%m-%Y") |
|
|
|
|
|
location = page_data['printouts']['Event:Location'][0] |
|
|
|
|
|
source = page_data['printouts']['Event:Source'][0] |
|
|
|
|
|
org = page_data['printouts']['Event:Organiser/s'][0]['fulltext'] |
|
|
|
|
|
|
|
|
|
|
|
opp_info = {'pagetitle': page_title, 'name': name, 'deadline': formatted_deadline, 'location': location, 'source' : source, 'org': org, 'text': ''} |
|
|
|
|
|
|
|
|
|
|
|
if type not in opp_page_list: |
|
|
|
|
|
opp_page_list[type] = [] |
|
|
|
|
|
|
|
|
|
|
|
opp_page_list[type].append(opp_info) |
|
|
|
|
|
|
|
|
|
|
|
return opp_page_list |
|
|
|
|
|
|
|
|
def homepage_new(self): |
|
|
def homepage_new(self): |
|
|
pages = ['Homepage'] |
|
|
pages = ['Homepage'] |
|
|
homepage_content = '' |
|
|
homepage_content = '' |
|
@ -39,20 +182,16 @@ class WikiApp(Flask): |
|
|
publication_page_list = self.fetch_all_pages(concepts) |
|
|
publication_page_list = self.fetch_all_pages(concepts) |
|
|
updated_cat_list = self.fetch_pages_cat(publication_page_list) |
|
|
updated_cat_list = self.fetch_pages_cat(publication_page_list) |
|
|
projects = updated_cat_list.get('Projects', []) |
|
|
projects = updated_cat_list.get('Projects', []) |
|
|
|
|
|
sorted_prj = dict(sorted(projects.items(), key=lambda x: x[1]['date'])) |
|
|
newsletters = updated_cat_list.get('Newsletters', []) |
|
|
newsletters = updated_cat_list.get('Newsletters', []) |
|
|
|
|
|
sorted_nl = dict(sorted(newsletters.items(), key=lambda x: x[1]['date'])) |
|
|
nav_elements = self.get_nav_menu() |
|
|
nav_elements = self.get_nav_menu() |
|
|
|
|
|
|
|
|
return render_template('publications.html', projects=projects, newsletters=newsletters, nav_elements=nav_elements) |
|
|
return render_template('publications.html', projects=sorted_prj, newsletters=sorted_nl, nav_elements=nav_elements) |
|
|
|
|
|
|
|
|
def fetch_meetups(self): |
|
|
def fetch_meetups(self): |
|
|
concepts = ['Meetups'] |
|
|
meetup_content, page_title = self.fetch_page('Meetups') |
|
|
# publication_page_list = self.fetch_all_pages(concepts) |
|
|
return render_template('meetups.html', content=meetup_content, nav_elements=self.get_nav_menu() ) |
|
|
# updated_cat_list = self.fetch_pages_cat(publication_page_list) |
|
|
|
|
|
# meetups = updated_cat_list.get('Meetups', []) |
|
|
|
|
|
nav_elements = self.get_nav_menu() |
|
|
|
|
|
meetup_content = self.fetch_page('Meetups') |
|
|
|
|
|
|
|
|
|
|
|
return render_template('meetups.html', content=meetup_content, nav_elements=nav_elements) |
|
|
|
|
|
|
|
|
|
|
|
def fetch_pages_cat(self, category_page_list): |
|
|
def fetch_pages_cat(self, category_page_list): |
|
|
all_pages_string = '|'.join(page for pages in category_page_list.values() for page in pages) |
|
|
all_pages_string = '|'.join(page for pages in category_page_list.values() for page in pages) |
|
@ -82,7 +221,7 @@ class WikiApp(Flask): |
|
|
def fetch_all_pages(self, categories): |
|
|
def fetch_all_pages(self, categories): |
|
|
category_page_list = {} |
|
|
category_page_list = {} |
|
|
for category in categories: |
|
|
for category in categories: |
|
|
response = requests.get(self.MEDIAWIKI_BASE_URL + self.BASE_API, params={'action': 'ask', 'query': '[[Concept:'+category+']]|?Article:Date', 'format': 'json', 'formatversion': '2'}) |
|
|
response = requests.get(self.MEDIAWIKI_BASE_URL + self.BASE_API, params={'action': 'ask', 'query': '[[Concept:'+category+']]|?Article:Date|?Article:Draft', 'format': 'json', 'formatversion': '2'}) |
|
|
data = response.json() |
|
|
data = response.json() |
|
|
page_title_timestamps = {} |
|
|
page_title_timestamps = {} |
|
|
for page_title, page_data in data['query']['results'].items(): |
|
|
for page_title, page_data in data['query']['results'].items(): |
|
@ -91,7 +230,8 @@ class WikiApp(Flask): |
|
|
raw_timestamp = raw_timestamp[2:] |
|
|
raw_timestamp = raw_timestamp[2:] |
|
|
lol = datetime.strptime(raw_timestamp, "%Y/%m/%d") |
|
|
lol = datetime.strptime(raw_timestamp, "%Y/%m/%d") |
|
|
formatted_date = lol.strftime("%d.%m.%Y") |
|
|
formatted_date = lol.strftime("%d.%m.%Y") |
|
|
page_title_timestamps[page_title] = {'date': formatted_date} |
|
|
if(page_data['printouts']['Article:Draft'][0] == 'f'): |
|
|
|
|
|
page_title_timestamps[page_title] = {'date': formatted_date, 'draft': page_data['printouts']['Article:Draft'][0]} |
|
|
|
|
|
|
|
|
category_page_list[category] = page_title_timestamps |
|
|
category_page_list[category] = page_title_timestamps |
|
|
return category_page_list |
|
|
return category_page_list |
|
@ -126,7 +266,13 @@ class WikiApp(Flask): |
|
|
page_title = data['parse']['title'] |
|
|
page_title = data['parse']['title'] |
|
|
page_content = data['parse']['text']['*'] |
|
|
page_content = data['parse']['text']['*'] |
|
|
page_content = self.fix_html(page_content) |
|
|
page_content = self.fix_html(page_content) |
|
|
return page_content |
|
|
page_date = re.search(r'\d{4}-\d{2}-\d{2}', data['parse']['text']['*']) |
|
|
|
|
|
|
|
|
|
|
|
if(page_date): |
|
|
|
|
|
date = page_date.group(0) |
|
|
|
|
|
return page_content, page_title, date |
|
|
|
|
|
else: |
|
|
|
|
|
return page_content, page_title |
|
|
|
|
|
|
|
|
def get_nav_menu(self): |
|
|
def get_nav_menu(self): |
|
|
response = requests.get(self.MEDIAWIKI_BASE_URL + self.BASE_API, params={'action': 'ask', 'query': '[[Concept:MainNavigation]]', 'format': 'json', 'formatversion': '2'}) |
|
|
response = requests.get(self.MEDIAWIKI_BASE_URL + self.BASE_API, params={'action': 'ask', 'query': '[[Concept:MainNavigation]]', 'format': 'json', 'formatversion': '2'}) |
|
@ -193,7 +339,6 @@ class WikiApp(Flask): |
|
|
resp = self.fetch_all_pages([collection]) |
|
|
resp = self.fetch_all_pages([collection]) |
|
|
data = self.fetch_pages_cat(resp) |
|
|
data = self.fetch_pages_cat(resp) |
|
|
return render_template('collection.html', nav_elements=self.get_nav_menu(), title=collection, collection=resp[collection]) |
|
|
return render_template('collection.html', nav_elements=self.get_nav_menu(), title=collection, collection=resp[collection]) |
|
|
|
|
|
|
|
|
# Route for favicon.ico to prevent Flask from raising an error |
|
|
# Route for favicon.ico to prevent Flask from raising an error |
|
|
def favicon(self): |
|
|
def favicon(self): |
|
|
return Response('', status=200) |
|
|
return Response('', status=200) |
|
|