aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralyx <alyx@aleteoryx.me>2023-11-25 22:31:49 -0500
committeralyx <alyx@aleteoryx.me>2023-11-25 22:31:49 -0500
commite21e42e832e4ac633a9d48f6e30c34a9011008bc (patch)
treea059574bd3fe1279e495ce0f8e2ac0810586184d
parent646d743dce4a3704febfa28be3abce405823baef (diff)
downloadbbss.py-e21e42e832e4ac633a9d48f6e30c34a9011008bc.tar.gz
bbss.py-e21e42e832e4ac633a9d48f6e30c34a9011008bc.tar.bz2
bbss.py-e21e42e832e4ac633a9d48f6e30c34a9011008bc.zip
Main interface done. Up next: docs, logging, and polish
-rw-r--r--src/bbss/__init__.py3
-rw-r--r--src/bbss/friends.py16
-rw-r--r--src/bbss/lists.py6
-rw-r--r--src/bbss/site.py51
-rw-r--r--src/bbss/sizes.py8
5 files changed, 76 insertions, 8 deletions
diff --git a/src/bbss/__init__.py b/src/bbss/__init__.py
index 6edc60d..98e45f5 100644
--- a/src/bbss/__init__.py
+++ b/src/bbss/__init__.py
@@ -1 +1,2 @@
-__all__ = ["lists", "buttons", "friends"]
+__all__ = ["lists", "buttons", "friends", "site", "sizes", "DEFAULT_PATHS"]
+DEFAULT_PATHS = ["/BBSS", "/.well-known/BBSS", "/badges", "/buttons", ""]
diff --git a/src/bbss/friends.py b/src/bbss/friends.py
index cd5e7cf..d0aa884 100644
--- a/src/bbss/friends.py
+++ b/src/bbss/friends.py
@@ -1,4 +1,6 @@
from .lists import BaseListFile, ListFileEntry, parse_listfile
+from .site import Site
+from . import DEFAULT_PATHS
from dataclasses import dataclass
from typing import cast, Optional
from collections.abc import Sequence
@@ -28,13 +30,19 @@ class FriendListFileEntry(ListFileEntry):
self.__setattr__('scheme', m.group('scheme') or None)
self.__setattr__('domain', m.group('domain'))
self.__setattr__('path', m.group('path').removesuffix('/'))
- self.__setattr__('url', (self.scheme if self.scheme else 'https') + '://' + self.domain + (self.path if self.path else '/BBSS') + '/')
+ self.__setattr__('url', (self.scheme if self.scheme else 'https') + '://' + self.domain + (self.path if self.path is not None else ""))
def exists(self) -> bool:
- return requests.head(self.url).ok
+ if self.path is not None:
+ return requests.head(self.url + "/sizes.txt").ok or requests.head(self.url + "/88x31/list.txt").ok
+ else:
+ for default in DEFAULT_PATHS:
+ if requests.head(default + "sizes.txt").ok or requests.head(default + "/88x31/list.txt").ok:
+ return True
+ return False
- def get(self) -> requests.Response:
- return requests.get(self.url)
+ def get(self) -> Site:
+ return Site(self.domain, self.path, scheme = self.scheme)
class FriendListFile(BaseListFile[FriendListFileEntry]):
def __init__(self, contents: str):
diff --git a/src/bbss/lists.py b/src/bbss/lists.py
index ba6955a..5bcdddf 100644
--- a/src/bbss/lists.py
+++ b/src/bbss/lists.py
@@ -6,14 +6,14 @@ import requests
T = TypeVar('T')
def parse_listfile(contents: str, ctor: Callable[[str, Optional[str]], T]) -> List[T]:
acc = []
- comment_acc = ""
+ comment_acc = []
for line in contents.splitlines():
if line.startswith("#"):
continue
elif line.startswith("##"):
- comment_acc += line[2:].strip()
+ comment_acc.append(line[2:].strip())
else:
- acc.append(ctor(line, comment_acc if comment_acc else None))
+ acc.append(ctor(line, " ".join(comment_acc) if len(comment_acc) else None))
return acc
@dataclass(frozen=True)
diff --git a/src/bbss/site.py b/src/bbss/site.py
new file mode 100644
index 0000000..7e8871f
--- /dev/null
+++ b/src/bbss/site.py
@@ -0,0 +1,51 @@
+from .sizes import SizeListFile
+from .friends import FriendListFile
+from . import DEFAULT_PATHS
+from typing import Optional
+from collections.abc import Sequence
+import requests
+
+class Site:
+ def __init__(self, domain: str, path: Optional[str], *, scheme: Optional[str]):
+ base = (scheme if scheme is not None else "https") + "://" + domain
+
+ hit_sizefile = False
+
+ def check_sizefile(path: str) -> bool:
+ return requests.head(base + path + "/sizes.txt").ok
+ def check_defaultlist(path: str) -> bool:
+ return requests.head(base + path + "/88x31/list.txt").ok
+
+ def check_path(path: str):
+ if check_sizefile(path):
+ hit_sizefile = True
+ return True
+ elif check_defaultlist(path):
+ return True
+
+ if path is not None:
+ if not check_path(path):
+ raise Exception("Oh noes there's nothing.")
+ else:
+ self.using_default = False
+ else:
+ for potential in DEFAULT_PATHS:
+ if check_path(potential):
+ path = potential
+ self.using_default = True
+ break
+ else:
+ raise Exception("Oh noes there's nothing(no path specified).")
+
+ self.root = base + path
+
+ if hit_sizefile:
+ self.has_sizes_txt = True
+ self.sizes = SizeListFile.from_url(self.root + "/sizes.txt")
+ else:
+ self.has_sizes_txt = False
+ self.sizes = SizeListFile("88x31", self.root)
+
+ self.friends = FriendListFile.from_url(self.root + "/friends.txt")
+
+__all__ = ["Site"]
diff --git a/src/bbss/sizes.py b/src/bbss/sizes.py
index 26818e9..0451458 100644
--- a/src/bbss/sizes.py
+++ b/src/bbss/sizes.py
@@ -27,6 +27,14 @@ class SizeListFile(BaseListFile[SizeListFileEntry]):
return SizeListFileEntry(entry, comment, root)
self._entries = parse_listfile(contents, construct_entry)
+ for entry in self._entries:
+ if entry.entry == "88x31":
+ break
+ else:
+ default = SizeListFileEntry("88x31", None, root)
+ if default.exists():
+ self._entries.append(default)
+
@classmethod
def from_url(cls, url: str) -> Optional[Self]:
(root, _, _) = url.rpartition('/')