On améliore l'intégration d'événements facebook
This commit is contained in:
parent
b57928664c
commit
43825f2801
@ -39,7 +39,8 @@ class Event:
|
|||||||
"day_time_sentence",
|
"day_time_sentence",
|
||||||
"event_place",
|
"event_place",
|
||||||
"comet_neighboring_siblings"],
|
"comet_neighboring_siblings"],
|
||||||
["event_description"]
|
["event_description"],
|
||||||
|
["start_timestamp", "end_timestamp"]
|
||||||
]
|
]
|
||||||
rules = {
|
rules = {
|
||||||
"event_description": { "description": ["text"]},
|
"event_description": { "description": ["text"]},
|
||||||
@ -52,11 +53,15 @@ class Event:
|
|||||||
self.fragments = {}
|
self.fragments = {}
|
||||||
self.elements = {}
|
self.elements = {}
|
||||||
self.neighbor_events = None
|
self.neighbor_events = None
|
||||||
|
self.possible_end_timestamp = []
|
||||||
self.add_fragment(i, event)
|
self.add_fragment(i, event)
|
||||||
|
|
||||||
def add_fragment(self, i, event):
|
def add_fragment(self, i, event):
|
||||||
self.fragments[i] = event
|
self.fragments[i] = event
|
||||||
|
|
||||||
|
if Event.keys[i] == ["start_timestamp", "end_timestamp"]:
|
||||||
|
self.get_possible_end_timestamp(i, event)
|
||||||
|
else:
|
||||||
for k in Event.keys[i]:
|
for k in Event.keys[i]:
|
||||||
if k == "comet_neighboring_siblings":
|
if k == "comet_neighboring_siblings":
|
||||||
self.get_neighbor_events(event[k])
|
self.get_neighbor_events(event[k])
|
||||||
@ -69,6 +74,8 @@ class Event:
|
|||||||
else:
|
else:
|
||||||
self.elements[k] = event[k]
|
self.elements[k] = event[k]
|
||||||
|
|
||||||
|
def get_possible_end_timestamp(self, i, data):
|
||||||
|
self.possible_end_timestamp.append(dict((k, data[k]) for k in Event.keys[i]))
|
||||||
|
|
||||||
def get_neighbor_events(self, data):
|
def get_neighbor_events(self, data):
|
||||||
self.neighbor_events = [SimpleEvent(d) for d in data]
|
self.neighbor_events = [SimpleEvent(d) for d in data]
|
||||||
@ -77,35 +84,48 @@ class Event:
|
|||||||
return str(self.elements) + "\n Neighbors: " + ", ".join([ne.elements["id"] for ne in self.neighbor_events])
|
return str(self.elements) + "\n Neighbors: " + ", ".join([ne.elements["id"] for ne in self.neighbor_events])
|
||||||
|
|
||||||
def consolidate_current_event(self):
|
def consolidate_current_event(self):
|
||||||
if self.neighbor_events is not None and "id" in self.elements:
|
if self.neighbor_events is not None and "id" in self.elements and "end_timestamp" not in self.elements:
|
||||||
id = self.elements["id"]
|
id = self.elements["id"]
|
||||||
for ne in self.neighbor_events:
|
for ne in self.neighbor_events:
|
||||||
if ne.elements["id"] == id:
|
if ne.elements["id"] == id:
|
||||||
self.elements["end_timestamp"] = ne.elements["end_timestamp"]
|
self.elements["end_timestamp"] = ne.elements["end_timestamp"]
|
||||||
|
|
||||||
def find_event_fragment_in_array(array, event):
|
if "end_timestamp" not in self.elements and len(self.possible_end_timestamp) != 0:
|
||||||
|
for s in self.possible_end_timestamp:
|
||||||
|
if s["start_timestamp"] == self.elements["start_timestamp"]:
|
||||||
|
self.elements["end_timestamp"] = s["end_timestamp"]
|
||||||
|
break
|
||||||
|
|
||||||
|
def find_event_fragment_in_array(array, event, first = True):
|
||||||
if isinstance(array, dict):
|
if isinstance(array, dict):
|
||||||
|
|
||||||
|
seen = False
|
||||||
for i, ks in enumerate(Event.keys):
|
for i, ks in enumerate(Event.keys):
|
||||||
if len(ks) == len([k for k in ks if k in array]):
|
if len(ks) == len([k for k in ks if k in array]):
|
||||||
|
seen = True
|
||||||
if event is None:
|
if event is None:
|
||||||
event = Event(i, array,)
|
event = Event(i, array)
|
||||||
else:
|
else:
|
||||||
event.add_fragment(i, array)
|
event.add_fragment(i, array)
|
||||||
else:
|
# only consider the first of Event.keys
|
||||||
|
break
|
||||||
|
if not seen:
|
||||||
for k in array:
|
for k in array:
|
||||||
event = Event.find_event_fragment_in_array(array[k], event)
|
event = Event.find_event_fragment_in_array(array[k], event, False)
|
||||||
elif isinstance(array, list):
|
elif isinstance(array, list):
|
||||||
for e in array:
|
for e in array:
|
||||||
event = Event.find_event_fragment_in_array(e, event)
|
event = Event.find_event_fragment_in_array(e, event, False)
|
||||||
|
|
||||||
if event is not None:
|
if event is not None and first:
|
||||||
event.consolidate_current_event()
|
event.consolidate_current_event()
|
||||||
return event
|
return event
|
||||||
|
|
||||||
|
|
||||||
#url="https://www.facebook.com/events/ical/export/?eid=2294200007432315"
|
#url="https://www.facebook.com/events/ical/export/?eid=2294200007432315"
|
||||||
url="https://www.facebook.com/events/2294199997432316/2294200007432315/"
|
#url="https://www.facebook.com/events/2294199997432316/2294200007432315/"
|
||||||
|
#url="https://www.facebook.com/events/635247792092358/"
|
||||||
|
url="https://www.facebook.com/events/872781744074648"
|
||||||
|
url="https://www.facebook.com/events/1432798543943663?"
|
||||||
#url_cal = "https://www.facebook.com/events/ical/export/?eid=993406668581410"
|
#url_cal = "https://www.facebook.com/events/ical/export/?eid=993406668581410"
|
||||||
#url="https://jmtrivial.info"
|
#url="https://jmtrivial.info"
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ def create_event_from_submission(self, url):
|
|||||||
logger.info(f"{url=}")
|
logger.info(f"{url=}")
|
||||||
|
|
||||||
if len(Event.objects.filter(reference_urls__contains=[url])) != 0:
|
if len(Event.objects.filter(reference_urls__contains=[url])) != 0:
|
||||||
logger.info("Already known url: ", url)
|
logger.info("Already known url: %s", url)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
logger.info("About to create event from submission")
|
logger.info("About to create event from submission")
|
||||||
@ -43,8 +43,6 @@ def create_event_from_submission(self, url):
|
|||||||
for e in events:
|
for e in events:
|
||||||
e.save()
|
e.save()
|
||||||
|
|
||||||
except BadHeaderError:
|
|
||||||
logger.info("BadHeaderError")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
|
||||||
|
@ -42,52 +42,152 @@ class Extractor:
|
|||||||
|
|
||||||
class ExtractorFacebook(Extractor):
|
class ExtractorFacebook(Extractor):
|
||||||
|
|
||||||
|
class SimpleFacebookEvent:
|
||||||
|
|
||||||
|
def __init__(self, data):
|
||||||
|
self.elements = {}
|
||||||
|
|
||||||
|
for key in ["id", "start_timestamp", "end_timestamp"]:
|
||||||
|
self.elements[key] = data[key] if key in data else None
|
||||||
|
|
||||||
|
if "parent_event" in data:
|
||||||
|
self.parent = ExtractorFacebook.SimpleFacebookEvent(data["parent_event"])
|
||||||
|
|
||||||
|
|
||||||
class FacebookEvent:
|
class FacebookEvent:
|
||||||
|
|
||||||
name = "event"
|
name = "event"
|
||||||
keys = ["start_time_formatted", 'start_timestamp', 'is_past', "name", "price_info", "cover_media_renderer", "event_creator", "id", "day_time_sentence", "event_place", "comet_neighboring_siblings"]
|
keys = [
|
||||||
|
["start_time_formatted", 'start_timestamp',
|
||||||
|
'is_past',
|
||||||
|
"name",
|
||||||
|
"price_info",
|
||||||
|
"cover_media_renderer",
|
||||||
|
"event_creator",
|
||||||
|
"id",
|
||||||
|
"day_time_sentence",
|
||||||
|
"event_place",
|
||||||
|
"comet_neighboring_siblings"],
|
||||||
|
["event_description"],
|
||||||
|
["start_timestamp", "end_timestamp"]
|
||||||
|
]
|
||||||
|
rules = {
|
||||||
|
"event_description": { "description": ["text"]},
|
||||||
|
"cover_media_renderer": {"image_alt": ["cover_photo", "photo", "accessibility_caption"], "image": ["cover_photo", "photo", "full_image", "uri"]},
|
||||||
|
"event_creator": { "event_creator_name": ["name"], "event_creator_url": ["url"] },
|
||||||
|
"event_place": {"event_place_name": ["name"] }
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, event):
|
def __init__(self, i, event):
|
||||||
self.data = event
|
self.fragments = {}
|
||||||
|
self.elements = {}
|
||||||
|
self.neighbor_events = None
|
||||||
|
self.possible_end_timestamp = []
|
||||||
|
self.add_fragment(i, event)
|
||||||
|
|
||||||
|
def get_element(self, key):
|
||||||
|
return self.elements[key] if key in self.elements else None
|
||||||
|
|
||||||
|
|
||||||
|
def get_element_datetime(self, key):
|
||||||
|
v = self.get_element(key)
|
||||||
|
return datetime.fromtimestamp(v) if v is not None else None
|
||||||
|
|
||||||
|
def add_fragment(self, i, event):
|
||||||
|
self.fragments[i] = event
|
||||||
|
|
||||||
|
if ExtractorFacebook.FacebookEvent.keys[i] == ["start_timestamp", "end_timestamp"]:
|
||||||
|
self.get_possible_end_timestamp(i, event)
|
||||||
|
else:
|
||||||
|
for k in ExtractorFacebook.FacebookEvent.keys[i]:
|
||||||
|
if k == "comet_neighboring_siblings":
|
||||||
|
self.get_neighbor_events(event[k])
|
||||||
|
elif k in ExtractorFacebook.FacebookEvent.rules:
|
||||||
|
for nk, rule in ExtractorFacebook.FacebookEvent.rules[k].items():
|
||||||
|
c = event[k]
|
||||||
|
for ki in rule:
|
||||||
|
c = c[ki]
|
||||||
|
self.elements[nk] = c
|
||||||
|
else:
|
||||||
|
self.elements[k] = event[k]
|
||||||
|
|
||||||
|
|
||||||
|
def get_possible_end_timestamp(self, i, data):
|
||||||
|
self.possible_end_timestamp.append(dict((k, data[k]) for k in ExtractorFacebook.FacebookEvent.keys[i]))
|
||||||
|
|
||||||
|
|
||||||
|
def get_neighbor_events(self, data):
|
||||||
|
self.neighbor_events = [ExtractorFacebook.SimpleFacebookEvent(d) for d in data]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.data["name"]
|
return str(self.elements) + "\n Neighbors: " + ", ".join([ne.elements["id"] for ne in self.neighbor_events])
|
||||||
|
|
||||||
def find_event_in_array(array):
|
def consolidate_current_event(self):
|
||||||
|
if self.neighbor_events is not None and "id" in self.elements and "end_timestamp" not in self.elements:
|
||||||
|
if self.neighbor_events is not None and "id" in self.elements:
|
||||||
|
id = self.elements["id"]
|
||||||
|
for ne in self.neighbor_events:
|
||||||
|
if ne.elements["id"] == id:
|
||||||
|
self.elements["end_timestamp"] = ne.elements["end_timestamp"]
|
||||||
|
|
||||||
|
if "end_timestamp" not in self.elements and len(self.possible_end_timestamp) != 0:
|
||||||
|
for s in self.possible_end_timestamp:
|
||||||
|
if s["start_timestamp"] == self.elements["start_timestamp"]:
|
||||||
|
self.elements["end_timestamp"] = s["end_timestamp"]
|
||||||
|
break
|
||||||
|
|
||||||
|
def find_event_fragment_in_array(array, event, first = True):
|
||||||
if isinstance(array, dict):
|
if isinstance(array, dict):
|
||||||
if len(ExtractorFacebook.FacebookEvent.keys) == len([k for k in ExtractorFacebook.FacebookEvent.keys if k in array]):
|
|
||||||
return ExtractorFacebook.FacebookEvent(array)
|
seen = False
|
||||||
|
for i, ks in enumerate(ExtractorFacebook.FacebookEvent.keys):
|
||||||
|
if len(ks) == len([k for k in ks if k in array]):
|
||||||
|
seen = True
|
||||||
|
if event is None:
|
||||||
|
event = ExtractorFacebook.FacebookEvent(i, array)
|
||||||
else:
|
else:
|
||||||
|
event.add_fragment(i, array)
|
||||||
|
# only consider the first of FacebookEvent.keys
|
||||||
|
break
|
||||||
|
if not seen:
|
||||||
for k in array:
|
for k in array:
|
||||||
v = ExtractorFacebook.FacebookEvent.find_event_in_array(array[k])
|
event = ExtractorFacebook.FacebookEvent.find_event_fragment_in_array(array[k], event, False)
|
||||||
if v != None:
|
|
||||||
return v
|
|
||||||
elif isinstance(array, list):
|
elif isinstance(array, list):
|
||||||
for e in array:
|
for e in array:
|
||||||
v = ExtractorFacebook.FacebookEvent.find_event_in_array(e)
|
event = ExtractorFacebook.FacebookEvent.find_event_fragment_in_array(e, event, False)
|
||||||
if v != None:
|
|
||||||
return v
|
if event is not None and first:
|
||||||
return None
|
event.consolidate_current_event()
|
||||||
|
return event
|
||||||
|
|
||||||
|
|
||||||
def build_event(self, url):
|
def build_event(self, url):
|
||||||
from .models import Event
|
from .models import Event
|
||||||
# TODO
|
|
||||||
return Event(title=self.data["name"],
|
return Event(title=self.get_element("name"),
|
||||||
status=Event.STATUS.DRAFT,
|
status=Event.STATUS.DRAFT,
|
||||||
start_day=datetime.fromtimestamp(self.data["start_timestamp"]),
|
start_day=self.get_element_datetime("start_timestamp"),
|
||||||
|
start_time=self.get_element_datetime("start_timestamp"),
|
||||||
|
end_day=self.get_element_datetime("end_timestamp"),
|
||||||
|
end_time=self.get_element_datetime("end_timestamp"),
|
||||||
|
location=self.get_element("event_place_name"),
|
||||||
|
description=self.get_element("description"),
|
||||||
|
image=self.get_element("image"),
|
||||||
|
image_alt=self.get_element("image_alt"),
|
||||||
reference_urls=[url])
|
reference_urls=[url])
|
||||||
|
|
||||||
|
|
||||||
def process_page(txt, url):
|
def process_page(txt, url):
|
||||||
|
|
||||||
|
fevent = None
|
||||||
soup = BeautifulSoup(txt, "html.parser")
|
soup = BeautifulSoup(txt, "html.parser")
|
||||||
for json_script in soup.find_all('script', type="application/json"):
|
for json_script in soup.find_all('script', type="application/json"):
|
||||||
json_txt = json_script.get_text()
|
json_txt = json_script.get_text()
|
||||||
json_struct = json.loads(json_txt)
|
json_struct = json.loads(json_txt)
|
||||||
fevent = ExtractorFacebook.FacebookEvent.find_event_in_array(json_struct)
|
fevent = ExtractorFacebook.FacebookEvent.find_event_fragment_in_array(json_struct, fevent)
|
||||||
if fevent != None:
|
|
||||||
logger.info(str(fevent.data))
|
|
||||||
|
|
||||||
|
if fevent is not None:
|
||||||
|
logger.info("Facebook event: " + str(fevent))
|
||||||
result = fevent.build_event(url)
|
result = fevent.build_event(url)
|
||||||
return [result]
|
return [result]
|
||||||
|
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 4.2.1 on 2023-11-11 17:42
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('agenda_culturel', '0013_staticcontent_url_path'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='event',
|
||||||
|
name='image',
|
||||||
|
field=models.URLField(blank=True, help_text='URL of the illustration image', max_length=1024, null=True, verbose_name='Illustration'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='event',
|
||||||
|
name='image_alt',
|
||||||
|
field=models.CharField(blank=True, help_text='Alternative text used by screen readers for the image', max_length=1024, null=True, verbose_name='Illustration description'),
|
||||||
|
),
|
||||||
|
]
|
@ -107,8 +107,8 @@ class Event(models.Model):
|
|||||||
|
|
||||||
description = models.TextField(verbose_name=_('Description'), help_text=_('General description of the event'), blank=True, null=True)
|
description = models.TextField(verbose_name=_('Description'), help_text=_('General description of the event'), blank=True, null=True)
|
||||||
|
|
||||||
image = models.URLField(verbose_name=_('Illustration'), help_text=_("URL of the illustration image"), max_length=200, blank=True, null=True)
|
image = models.URLField(verbose_name=_('Illustration'), help_text=_("URL of the illustration image"), max_length=1024, blank=True, null=True)
|
||||||
image_alt = models.CharField(verbose_name=_('Illustration description'), help_text=_('Alternative text used by screen readers for the image'), blank=True, null=True, max_length=512)
|
image_alt = models.CharField(verbose_name=_('Illustration description'), help_text=_('Alternative text used by screen readers for the image'), blank=True, null=True, max_length=1024)
|
||||||
|
|
||||||
reference_urls = ArrayField(models.URLField(max_length=512), verbose_name=_('URLs'), help_text=_("List of all the urls where this event can be found."), blank=True, null=True)
|
reference_urls = ArrayField(models.URLField(max_length=512), verbose_name=_('URLs'), help_text=_("List of all the urls where this event can be found."), blank=True, null=True)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user