from pathlib import Path from typing import Optional from urllib.parse import urljoin import requests from masto_ld.creds import Mediawiki_Creds from masto_ld.formats.wiki import WikiPage from masto_ld.logger import init_logger from masto_ld.config import Config class Wiki: def __init__(self, config:Config, api_suffix:str="/api.php", index_page="Discord Messages", log_dir:Path=Path('/var/www/wikibot')): self.url = config.WIKI_URL self.api_url = urljoin(self.url, api_suffix) self.creds = Mediawiki_Creds(config.WIKI_USER, config.WIKI_PASSWORD) self.sess = None self.index_page = index_page self.logger = init_logger('wiki_interface', basedir=log_dir) self.login(self.creds) def login(self, creds:Mediawiki_Creds): # get token to log in sess = requests.Session() login_token = sess.get( self.api_url, params={ "action":"query", "meta":"tokens", "type":"login", "format":"json" }, verify=False ).json()['query']['tokens']['logintoken'] login_result = sess.post( self.api_url, data = { "action":"login", "lgname":creds.user, "lgpassword":creds.password, "lgtoken": login_token, "format": "json" }, verify=False ) assert login_result.json()['login']['result'] == "Success" self.sess = sess def get_page(self, page:str) -> Optional[WikiPage]: content = self.sess.get( self.api_url, params={ 'action':'parse', 'page': page, 'prop': 'wikitext', 'formatversion':'2', 'format':'json' } ).json() if content.get('error', {}).get('code', '') == 'missingtitle': # Page does not exist! self.logger.debug("Page does not exist") return None self.logger.debug(f"Got Page content:") self.logger.debug(content) return WikiPage.from_source(title=content['parse']['title'], source=content['parse']['wikitext']) def new_page(self, page, text): token = self.sess.get( self.api_url, params={ "action": "query", "meta": "tokens", "format": "json" }, verify=False ).json()['query']['tokens']['csrftoken'] result = self.sess.post( self.api_url, data={ "action": "edit", "title": page, "appendtext": text, "format": "json", "token": token } ) def insert_text(self, page, section, text): # TODO: Move finding section IDs into the page class! page_text = self.get_page(page) matching_section = -1 if page_text is not None: # find section number sections = page_text.content.get_sections() for i, page_section in enumerate(sections): if page_section.title is not None and page_section.title.strip().lower() == section.lower(): matching_section = i break token = self.sess.get( self.api_url, params={ "action": "query", "meta": "tokens", "format": "json" }, verify=False ).json()['query']['tokens']['csrftoken'] if matching_section >= 0: print(f'found matching section {matching_section}') result = self.sess.post( self.api_url, data={ "action":"edit", "title":page, "section":str(matching_section), "appendtext":text, "format":"json", "token":token } ) else: self.logger.debug('making new section') result = self.sess.post( self.api_url, data={ "action":"edit", "title":page, "section":"new", "sectiontitle":section, "appendtext":text, "format":"json", "token":token } ) return result