2021-05-30 11:23:48 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, Optional
|
|
|
|
from urllib.parse import urlparse, urlunparse
|
2022-07-26 13:48:44 +00:00
|
|
|
import logging
|
2022-06-22 17:17:20 +00:00
|
|
|
import asyncpg
|
|
|
|
|
2022-07-26 13:48:44 +00:00
|
|
|
from exceptions import NoDomain
|
2021-05-30 11:23:48 +00:00
|
|
|
from src.config import settings
|
|
|
|
from src.domain import Domain
|
2021-05-30 13:31:51 +00:00
|
|
|
from src.irc_feed import AioIRCCat
|
2021-05-30 11:23:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
from src.wiki import Wiki
|
|
|
|
|
2022-07-26 13:48:44 +00:00
|
|
|
logger = logging.getLogger("rcgcdb.domain_manager")
|
2021-05-30 11:23:48 +00:00
|
|
|
|
|
|
|
class DomainManager:
|
|
|
|
def __init__(self):
|
|
|
|
self.domains: dict[str, Domain] = {}
|
|
|
|
|
2022-06-22 17:17:20 +00:00
|
|
|
async def webhook_update(self, connection: asyncpg.Connection, pid: int, channel: str, payload: str):
|
|
|
|
"""Callback for database listener. Used to update our domain cache on changes such as new wikis or removed wikis"""
|
|
|
|
# TODO Write a trigger for pub/sub in database/Wiki-Bot repo
|
|
|
|
split_payload = payload.split(" ")
|
|
|
|
if len(split_payload) < 2:
|
|
|
|
raise ValueError("Improper pub/sub message! Pub/sub payload: {}".format(payload))
|
|
|
|
if split_payload[0] == "ADD":
|
2022-08-09 10:57:40 +00:00
|
|
|
await self.new_wiki(Wiki(split_payload[1], None, None))
|
2022-06-22 17:17:20 +00:00
|
|
|
elif split_payload[0] == "REMOVE":
|
2022-07-24 20:02:25 +00:00
|
|
|
try:
|
|
|
|
results = await connection.fetch("SELECT * FROM rcgcdw WHERE wiki = $1;", split_payload[1])
|
|
|
|
if len(results) > 0:
|
|
|
|
return
|
|
|
|
except asyncpg.IdleSessionTimeoutError:
|
|
|
|
logger.error("Couldn't check amount of webhooks with {} wiki!".format(split_payload[1]))
|
|
|
|
return
|
2022-06-22 17:17:20 +00:00
|
|
|
self.remove_wiki(split_payload[1])
|
|
|
|
else:
|
|
|
|
raise ValueError("Unknown pub/sub command! Payload: {}".format(payload))
|
|
|
|
|
2021-07-09 12:55:23 +00:00
|
|
|
async def new_wiki(self, wiki: Wiki):
|
2021-05-30 11:23:48 +00:00
|
|
|
"""Finds a domain for the wiki and adds a wiki to the domain object.
|
|
|
|
|
|
|
|
:parameter wiki - Wiki object to be added"""
|
|
|
|
wiki_domain = self.get_domain(wiki.script_url)
|
|
|
|
try:
|
|
|
|
self.domains[wiki_domain].add_wiki(wiki)
|
|
|
|
except KeyError:
|
2021-07-09 12:55:23 +00:00
|
|
|
new_domain = await self.new_domain(wiki_domain)
|
|
|
|
new_domain.add_wiki(wiki)
|
|
|
|
|
2022-08-09 14:08:30 +00:00
|
|
|
def remove_domain(self, domain):
|
|
|
|
domain.destoy()
|
|
|
|
del self.domains[domain]
|
|
|
|
|
2021-07-09 12:55:23 +00:00
|
|
|
def remove_wiki(self, script_url: str):
|
|
|
|
wiki_domain = self.get_domain(script_url)
|
|
|
|
try:
|
|
|
|
domain = self.domains[wiki_domain]
|
|
|
|
except KeyError:
|
|
|
|
raise NoDomain
|
|
|
|
else:
|
|
|
|
domain.remove_wiki(script_url)
|
2022-08-09 14:08:30 +00:00
|
|
|
if len(domain) == 0:
|
|
|
|
self.remove_domain(domain)
|
2021-05-30 11:23:48 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_domain(url: str) -> str:
|
|
|
|
"""Returns a domain for given URL (for example fandom.com, wikipedia.org)"""
|
|
|
|
parsed_url = urlparse(url)
|
|
|
|
return ".".join(urlunparse((*parsed_url[0:2], "", "", "", "")).split(".")[-2:])
|
|
|
|
|
2022-08-09 10:57:40 +00:00
|
|
|
def return_domain(self, domain: str):
|
|
|
|
return self.domains[domain]
|
|
|
|
|
2021-05-30 13:31:51 +00:00
|
|
|
async def new_domain(self, name: str) -> Domain:
|
|
|
|
domain_object = Domain(name)
|
|
|
|
for irc_server in settings["irc_servers"].keys():
|
|
|
|
if name in settings["irc_servers"][irc_server]["domains"]:
|
|
|
|
domain_object.set_irc(AioIRCCat(settings["irc_servers"][irc_server]["irc_channel_mapping"], domain_object))
|
|
|
|
break # Allow only one IRC for a domain
|
|
|
|
self.domains[name] = domain_object
|
2021-05-30 11:23:48 +00:00
|
|
|
return self.domains[name]
|
|
|
|
|
2022-08-09 10:57:40 +00:00
|
|
|
def run_all_domains(self):
|
2021-06-05 11:12:23 +00:00
|
|
|
for domain in self.domains.values():
|
|
|
|
domain.run_domain()
|
2021-05-30 11:23:48 +00:00
|
|
|
|
2022-06-16 21:12:10 +00:00
|
|
|
|
2021-05-30 11:23:48 +00:00
|
|
|
domains = DomainManager()
|