""" undo wrapper activity """ from dataclasses import dataclass from typing import List from django.apps import apps from .base_activity import ActivityObject, Signature, resolve_remote_id from .book import Edition @dataclass(init=False) class Verb(ActivityObject): """generic fields for activities - maybe an unecessary level of abstraction but w/e""" actor: str object: ActivityObject def action(self): """ usually we just want to save, this can be overridden as needed """ self.object.to_model() @dataclass(init=False) class Create(Verb): """ Create activity """ to: List cc: List signature: Signature = None type: str = "Create" @dataclass(init=False) class Delete(Verb): """ Create activity """ to: List cc: List type: str = "Delete" def action(self): """ find and delete the activity object """ obj = self.object.to_model(save=False, allow_create=False) obj.delete() @dataclass(init=False) class Update(Verb): """ Update activity """ to: List type: str = "Update" def action(self): """ update a model instance from the dataclass """ self.object.to_model(allow_create=False) @dataclass(init=False) class Undo(Verb): """ Undo an activity """ type: str = "Undo" def action(self): """ find and remove the activity object """ if isinstance(self.object, str): # it may be that sometihng should be done with these, but idk what # this seems just to be coming from pleroma return # this is so hacky but it does make it work.... # (because you Reject a request and Undo a follow model = None if self.object.type == "Follow": model = apps.get_model("bookwyrm.UserFollows") obj = self.object.to_model(model=model, save=False, allow_create=False) if not obj: # this could be a folloq request not a follow proper model = apps.get_model("bookwyrm.UserFollowRequest") obj = self.object.to_model(model=model, save=False, allow_create=False) else: obj = self.object.to_model(model=model, save=False, allow_create=False) if not obj: # if we don't have the object, we can't undo it. happens a lot with boosts return obj.delete() @dataclass(init=False) class Follow(Verb): """ Follow activity """ object: str type: str = "Follow" def action(self): """ relationship save """ self.to_model() @dataclass(init=False) class Block(Verb): """ Block activity """ object: str type: str = "Block" def action(self): """ relationship save """ self.to_model() @dataclass(init=False) class Accept(Verb): """ Accept activity """ object: Follow type: str = "Accept" def action(self): """ find and remove the activity object """ obj = self.object.to_model(save=False, allow_create=False) obj.accept() @dataclass(init=False) class Reject(Verb): """ Reject activity """ object: Follow type: str = "Reject" def action(self): """ find and remove the activity object """ obj = self.object.to_model(save=False, allow_create=False) obj.reject() @dataclass(init=False) class Add(Verb): """Add activity """ target: str object: Edition type: str = "Add" notes: str = None order: int = 0 approved: bool = True def action(self): """ add obj to collection """ target = resolve_remote_id(self.target, refresh=False) # we want to get the related field that isn't the book, this is janky af sorry model = [t for t in type(target)._meta.related_objects if t.name != "edition"][ 0 ].related_model self.to_model(model=model) @dataclass(init=False) class Remove(Verb): """Remove activity """ target: ActivityObject type: str = "Remove" def action(self): """ find and remove the activity object """ target = resolve_remote_id(self.target, refresh=False) model = [t for t in type(target)._meta.related_objects if t.name != "edition"][ 0 ].related_model obj = self.to_model(model=model, save=False, allow_create=False) obj.delete() @dataclass(init=False) class Like(Verb): """ a user faving an object """ object: str type: str = "Like" def action(self): """ like """ self.to_model() @dataclass(init=False) class Announce(Verb): """ boosting a status """ object: str type: str = "Announce" def action(self): """ boost """ self.to_model()