Esempio n. 1
0
def api_new_question() -> _Response:
    source = _user_api_arg("content")
    if not source:
        raise ValueError("missing content")

    content, tags = parse_markdown(source)
    cc = [ID + "/followers"]

    for tag in tags:
        if tag["type"] == "Mention":
            cc.append(tag["href"])

    answers = []
    for i in range(4):
        a = _user_api_arg(f"answer{i}", default=None)
        if not a:
            break
        answers.append({
            "type": ap.ActivityType.NOTE.value,
            "name": a,
            "replies": {
                "type": ap.ActivityType.COLLECTION.value,
                "totalItems": 0
            },
        })

    open_for = int(_user_api_arg("open_for"))
    choices = {
        "endTime":
        ap.format_datetime(
            datetime.now(timezone.utc) + timedelta(minutes=open_for))
    }
    of = _user_api_arg("of")
    if of == "anyOf":
        choices["anyOf"] = answers
    else:
        choices["oneOf"] = answers

    raw_question = dict(
        attributedTo=MY_PERSON.id,
        cc=list(set(cc)),
        to=[ap.AS_PUBLIC],
        content=content,
        tag=tags,
        source={
            "mediaType": "text/markdown",
            "content": source
        },
        inReplyTo=None,
        **choices,
    )

    question = ap.Question(**raw_question)
    create = question.build_create()
    create_id = post_to_outbox(create)

    Tasks.update_question_outbox(create_id, open_for)

    return _user_api_response(activity=create_id)
Esempio n. 2
0
def _add_answers_to_question(raw_doc: Dict[str, Any]) -> None:
    activity = raw_doc["activity"]
    if (ap._has_type(activity["type"], ap.ActivityType.CREATE)
            and "object" in activity and ap._has_type(
                activity["object"]["type"], ap.ActivityType.QUESTION)):
        for choice in activity["object"].get("oneOf",
                                             activity["object"].get("anyOf")):
            choice["replies"] = {
                "type":
                ap.ActivityType.COLLECTION.value,
                "totalItems":
                raw_doc["meta"].get("question_answers",
                                    {}).get(_answer_key(choice["name"]), 0),
            }
        now = datetime.now(timezone.utc)
        if format_datetime(now) >= activity["object"]["endTime"]:
            activity["object"]["closed"] = activity["object"]["endTime"]
Esempio n. 3
0
    def migrate(self) -> None:
        for data in find_activities({"meta.published": {"$exists": False}}):
            try:
                raw = data["activity"]
                # If the activity has its own `published` field, we'll use it
                if "published" in raw:
                    published = raw["published"]
                else:
                    # Otherwise, we take the date we received the activity as the published time
                    published = ap.format_datetime(data["_id"].generation_time)

                # Set the field in the DB
                update_one_activity(
                    {"_id": data["_id"]},
                    {"$set": {_meta(MetaKey.PUBLISHED): published}},
                )

            except Exception:
                logger.exception(f"failed to process activity {data!r}")
Esempio n. 4
0
def _load_emojis(root_dir: Path, base_url: str) -> None:
    if EMOJIS:
        return
    for emoji in (root_dir / "static" / "emojis").iterdir():
        mt = mimetypes.guess_type(emoji.name)[0]
        if mt and mt.startswith("image/"):
            name = emoji.name.split(".")[0]
            ap_emoji = dict(
                type=ap.ActivityType.EMOJI.value,
                name=f":{name}:",
                updated=ap.format_datetime(datetime.fromtimestamp(0.0).astimezone()),
                id=f"{base_url}/emoji/{name}",
                icon={
                    "mediaType": mt,
                    "type": ap.ActivityType.IMAGE.value,
                    "url": f"{base_url}/static/emojis/{emoji.name}",
                },
            )
            EMOJIS[emoji.name] = ap_emoji
            EMOJIS_BY_NAME[ap_emoji["name"]] = ap_emoji
Esempio n. 5
0
def gtnow(dtstr):
    return ap.format_datetime(datetime.now(timezone.utc)) > dtstr
Esempio n. 6
0
def now() -> str:
    return ap.format_datetime(datetime.now(timezone.utc))
Esempio n. 7
0
def published_after(dt: datetime) -> _SubQuery:
    return flag(MetaKey.PUBLISHED, {"$gt": ap.format_datetime(dt)})