Skip to content

Commit

Permalink
Create title change function and edit lock helper
Browse files Browse the repository at this point in the history
  • Loading branch information
rossjrw committed Jul 19, 2024
1 parent fcfce64 commit 3ad07ae
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 1 deletion.
35 changes: 35 additions & 0 deletions notifier/deletions.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,41 @@ def rename_invalid_user_config_pages(
continue


def rename_misnamed_user_config_pages(
local_config: LocalConfig, connection: Connection
) -> None:
"""Renames user configs to fix an error in the page creation link.
The link syntax breaks if it contains a space, but spaces are permitted in usernames. Therefore if a user has a space in their username, their user config create link will be broken and will have a nonsensical name.
Users are allowed to name their pages whatever they like but this cleans up that one case specifically.
"""
logger.info("Finding user configs from users with spaces in their name")
misnamed_configs = [
(slug, config)
for slug, config in fetch_user_configs(local_config, connection)
if " " in config["username"]
and config["title"] == config["username"].split(" ")[0]
]
logger.debug(
"Found misnamed configs to rename %s", {"count": len(misnamed_configs)}
)
for slug, config in misnamed_configs:
try:
connection.rename_page(
local_config["config_wiki"],
slug,
f"{local_config['user_config_category']}:{config['user_id']}",
)
except Exception as error:
logger.error(
"Couldn't rename config page %s",
{"slug": slug},
exc_info=error,
)
continue


def delete_prepared_invalid_user_pages(
local_config: LocalConfig, wikidot: Wikidot
) -> None:
Expand Down
83 changes: 82 additions & 1 deletion notifier/wikidot.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from contextlib import contextmanager
from functools import lru_cache
import logging
import re
import time
Expand Down Expand Up @@ -63,6 +65,10 @@ class OngoingConnectionError(Exception):
by trying it multiple times."""


class LockNotEstablished(Exception):
"""The requested edit lock could not be established."""


class Wikidot:
"""Connection to Wikidot facilitating communications with it."""

Expand Down Expand Up @@ -398,6 +404,7 @@ def get_contacts(self) -> EmailAddresses:
addresses[username.strip()] = address
return addresses

@lru_cache(maxsize=1)
def get_page_id(self, wiki_id: str, slug: str) -> int:
"""Get a page's ID from its source."""
try:
Expand All @@ -418,8 +425,80 @@ def get_page_id(self, wiki_id: str, slug: str) -> int:
cast(Match[str], re.search(r"pageId = ([0-9]+);", page)).group(1)
)

@contextmanager
def edit_lock(self, wiki_id: str, slug: str) -> Iterator[Tuple[str, str]]:
"""Establishes an edit lock to commit an edit to a page.
Exposes the lock id and secret to be used in an edit request.
Connection needs to be logged in.
"""
logger.debug(
"Establishing edit lock %s", {"wiki_id": wiki_id, "slug": slug}
)
page_id = self.get_page_id(wiki_id, slug)
response = self.module(
wiki_id,
"edit/PageEditModule",
page_id=str(page_id),
wiki_page=slug,
mode="page",
)
lock_id = str(response.get("lock_id"))
lock_secret = str(response.get("lock_secret"))
if response.get("locked", False) or not lock_id or not lock_secret:
logger.debug(
"Failed to acquire edit lock %s",
{"wiki_id": wiki_id, "slug": slug},
)
raise LockNotEstablished
try:
yield lock_id, lock_secret
except:
# If the edit fails, release the lock
logger.debug(
"Releasing edit lock %s", {"wiki_id": wiki_id, "slug": slug}
)
self.module(
wiki_id,
"Empty",
action="WikiPageAction",
event="removePageEditLock",
page_id="1453558361",
wiki_page=slug,
lock_id=lock_id,
lock_secret=lock_secret,
leave_draft="false",
)
raise

def edit_page_title(self, wiki_id: str, slug: str, title: str) -> None:
"""Changes the title of a page.
Connection needs to be logged in.
"""
page_id = self.get_page_id(wiki_id, slug)
with
logger.debug(
"Renaming page %s",
{
"with id": page_id,
"from slug": slug,
"to slug": to_slug,
"in wiki": wiki_id,
},
)
self.module(
wiki_id,
"Empty",
action="WikiPageAction",
event="renamePage",
page_id=str(page_id),
new_name=to_slug,
)

def rename_page(self, wiki_id: str, from_slug: str, to_slug: str) -> None:
"""Renames a page.
"""Renames (i.e. moves) a page.
Renames can take a while (30+ seconds) to take effect, so if
renaming for safe deletion, probably don't bother deleting until
Expand Down Expand Up @@ -449,6 +528,8 @@ def rename_page(self, wiki_id: str, from_slug: str, to_slug: str) -> None:
def delete_page(self, wiki_id: str, slug: str) -> None:
"""Deletes a page.
Very rarely, a delete semi-fails and leaves the page in a corrupted state where it can no longer be interacted with. To avoid this affecting anything, rename the page to something random first.
Connection needs to be logged in.
"""
if not slug.startswith("deleted:"):
Expand Down

0 comments on commit 3ad07ae

Please sign in to comment.