| 
															
																@@ -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 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 |