|
@@ -1,5 +1,6 @@
|
|
from dataclasses import dataclass
|
|
from dataclasses import dataclass
|
|
import datetime
|
|
import datetime
|
|
|
|
+import json
|
|
from passlib.apps import custom_app_context as pwd
|
|
from passlib.apps import custom_app_context as pwd
|
|
import peewee
|
|
import peewee
|
|
import playhouse.shortcuts
|
|
import playhouse.shortcuts
|
|
@@ -110,6 +111,43 @@ class User(Model):
|
|
admin_pane = v.AdminPane(invites=user_invites)
|
|
admin_pane = v.AdminPane(invites=user_invites)
|
|
return v.Config(username=self.name, admin_pane=admin_pane,)
|
|
return v.Config(username=self.name, admin_pane=admin_pane,)
|
|
|
|
|
|
|
|
+ def import_pinboard_data(self, stream):
|
|
|
|
+ try:
|
|
|
|
+ links = json.load(stream)
|
|
|
|
+ except json.decoder.JSONDecodeError as exn:
|
|
|
|
+ raise e.BadFileUpload("could not parse file as JSON")
|
|
|
|
+
|
|
|
|
+ if not isinstance(links, list):
|
|
|
|
+ raise e.BadFileUpload(f"expected a list")
|
|
|
|
+
|
|
|
|
+ # create and (for this session) cache the tags
|
|
|
|
+ tags = {}
|
|
|
|
+ for l in links:
|
|
|
|
+ if "tags" not in l:
|
|
|
|
+ raise e.BadFileUpload("missing key {exn.args[0]}")
|
|
|
|
+ for t in l["tags"].split():
|
|
|
|
+ if t in tags:
|
|
|
|
+ continue
|
|
|
|
+
|
|
|
|
+ tags[t] = Tag.get_or_create_tag(self, t)
|
|
|
|
+
|
|
|
|
+ with c.db.atomic():
|
|
|
|
+ for l in links:
|
|
|
|
+ try:
|
|
|
|
+ time = datetime.datetime.strptime(l["time"], "%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
+ ln = Link.create(
|
|
|
|
+ url=l["href"],
|
|
|
|
+ name=l["description"],
|
|
|
|
+ description=l["extended"],
|
|
|
|
+ private=l["shared"] == "no",
|
|
|
|
+ created=time,
|
|
|
|
+ user=self,
|
|
|
|
+ )
|
|
|
|
+ except KeyError as exn:
|
|
|
|
+ raise e.BadFileUpload(f"missing key {exn.args[0]}")
|
|
|
|
+ for t in l["tags"].split():
|
|
|
|
+ HasTag.get_or_create(link=ln, tag=tags[t])
|
|
|
|
+
|
|
|
|
|
|
class Link(Model):
|
|
class Link(Model):
|
|
"""
|
|
"""
|
|
@@ -145,8 +183,7 @@ class Link(Model):
|
|
)
|
|
)
|
|
for tag_name in link.tags:
|
|
for tag_name in link.tags:
|
|
tag = Tag.get_or_create_tag(user, tag_name)
|
|
tag = Tag.get_or_create_tag(user, tag_name)
|
|
- for t in tag.get_family():
|
|
|
|
- HasTag.get_or_create(link=l, tag=t)
|
|
|
|
|
|
+ HasTag.get_or_create(link=l, tag=tag)
|
|
return l
|
|
return l
|
|
|
|
|
|
def update_from_request(self, user: User, link: r.Link):
|
|
def update_from_request(self, user: User, link: r.Link):
|
|
@@ -266,6 +303,9 @@ class HasTag(Model):
|
|
if res is None:
|
|
if res is None:
|
|
res = HasTag.create(link=link, tag=tag)
|
|
res = HasTag.create(link=link, tag=tag)
|
|
|
|
|
|
|
|
+ if tag.parent:
|
|
|
|
+ HasTag.get_or_create(link, tag.parent)
|
|
|
|
+
|
|
return res
|
|
return res
|
|
|
|
|
|
|
|
|