Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 0 additions & 104 deletions scratchattach/site/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ def __init__(self, **entries) -> None:
self.parent_title = None
self._moderation_status = None

self.remix_tree_children: Optional[list[Project]] = None
self.remix_tree_parent: Optional[Project] = None

# Update attributes from entries dict:
self.__dict__.update(entries)

Expand Down Expand Up @@ -289,10 +286,6 @@ class Project(PartialProject):

:.thumbnail_url:

:.remix_parent:

:.remix_root:

:.loves: The project's love count

:.favorites: The project's favorite count
Expand Down Expand Up @@ -860,103 +853,6 @@ def visibility(self):
return requests.get(f"https://api.scratch.mit.edu/users/{self._session.username}/projects/{self.id}/visibility",
headers=self._headers, cookies=self._cookies).json()

def remix_tree(self) -> Project:
"""
Fetch & cache remix tree, and return remix root.
Cached remix tree children accessible via Project.remix_tree_children.
A parent project object that is linked to children is accessible via Project.remix_tree_parent

:return remix root project. All remixes in the tree are (in)directly linked.
"""

data: dict = requests.get(f"https://scratch.mit.edu/projects/{self.id}/remixtree/bare/").json()

mapping: dict[str, Project] = {}
root_id = data.pop("root_id")


# load up all projects
for curr_id, curr_data in data.items():
curr_data = data[curr_id]
if share_date := curr_data["datetime_shared"]:
share_date = share_date["$date"] / 1000

if curr_id == str(self.id):
curr_obj = self
else:
curr_obj = Project(id=curr_id)

curr_obj.title = curr_data["title"]
curr_obj.author_name = curr_data["username"]
curr_obj.favorites = curr_data["favorite_count"]
curr_obj.loves = curr_data["love_count"]
curr_obj._moderation_status = curr_data["moderation_status"]
curr_obj.share_date = share_date # timestamp
curr_obj.created = curr_data["datetime_created"]["$date"] / 1000
curr_obj.last_modified = curr_data["mtime"]["$date"] / 1000
curr_obj._session = self._session
curr_obj.remix_tree_children = []

# curr_obj._visibility=curr_data["visibility"]
# is_published=curr_data["is_published"]
# curr_obj.ctime = curr_data["ctime"]["$date"] / 1000

mapping[curr_id] = curr_obj

assert self in mapping.values()

# link projects
for curr_id, curr_data in data.items():
curr_data = data[curr_id]
curr_obj = mapping[curr_id]

parent_id = curr_data["parent_id"]
if parent := mapping.get(parent_id):
curr_obj.remix_tree_parent = parent
# parent cannot be None, as it is the if condition
parent.remix_tree_children.append(curr_obj) # type: ignore

return mapping[root_id]

def remix_tree_pretty(self, indent: int = 0, *, formatter: Optional[Callable[[Project, int], str]] = None):
"""
Prettily formats and indents the remix tree attached to this project. (does NOT start at root)
:param indent: default indent - recommend keeping this as 0
:param formatter: function that formats a single project with an indent. Return a string. Recommend starting with '\t' * indent
:return: Large string containing the formatted remix tree. For large trees, it is recommended to save it to a file.
"""
if not formatter:
formatter = lambda p, ind: f"{'\t' * ind}-P {p.title} ({p.id}) #{p.remix_depth}\n"

if self.remix_tree_children is None:
self.remix_tree()

assert isinstance(self.remix_tree_children, list)

ret = formatter(self, indent)
for child in self.remix_tree_children:
ret += child.remix_tree_pretty(indent + 1, formatter=formatter)

return ret

@property
def remix_depth(self) -> int:
"""
Get the 'remix depth' of this project - i.e. the number of layers of remixing until one reaches the remix root.
"""
if self.remix_tree_children is None:
self.remix_tree()

depth = 0
p = self
while p.remix_tree_parent:
# this could also be done recursively, but it can hit the recursion limit in extreme cases
# > and this happens often, because of remix chains
p = p.remix_tree_parent
depth += 1

return depth


# ------ #

Expand Down