Add an ephemeral similarity check page
- /similar (nav: Similar): drop a file to get the exact MD5 match, the perceptual matches against the library, and e621 IQDB candidates (auto-run for images when credentials are configured). Read-only — nothing enters the library. - SimilarityCheck model + /api/similarity/ (create/list/retrieve/delete) with signed preview URLs and an expires_at timestamp. - Temp files are wiped on startup (AppConfig.ready, file-only so no database access during initialization), lazily past SIMILARITY_TTL_MINUTES (default 30, env-overridable), on delete, and by manage.py cleanup_similarity. - uploadFile() takes a target path; .env.example documents the TTL.
This commit is contained in:
@@ -281,3 +281,32 @@ class MatchTask(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
return f"Match scan {self.id} ({self.status})"
|
||||
|
||||
|
||||
class SimilarityCheck(models.Model):
|
||||
"""An ephemeral image uploaded only to check what it looks like.
|
||||
|
||||
Never enters the library: files live in the media temp folder and are
|
||||
purged on startup, by the TTL and by `manage.py cleanup_similarity`.
|
||||
"""
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="similarity_checks",
|
||||
)
|
||||
file = models.FileField(upload_to="similarity/", blank=True)
|
||||
original_filename = models.CharField(max_length=255)
|
||||
md5 = models.CharField(max_length=32, db_index=True, blank=True, default="")
|
||||
size = models.BigIntegerField(default=0)
|
||||
results = models.JSONField(default=dict, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["-created_at"]
|
||||
|
||||
def __str__(self):
|
||||
return f"Similarity check {self.id} ({self.original_filename})"
|
||||
|
||||
Reference in New Issue
Block a user