Repository: supakeen/pinnwand (language: python)

Issue:
Is there a way to retrieve via API paste code from link?
Lets say i have a link to the paste. Is there a way to get the text stored under that text using API?


Discussion / hints:
There is no such route in the current API (`/api/v1`), though that needs to added. It seems weird that it's missing.

The deprecated API has one at (`/json/show/:paste-id`), for example: https://bpa.st/json/show/YDQA but it only shows the first file.

Fix patch:
diff --git a/src/pinnwand/handler/api_v1.py b/src/pinnwand/handler/api_v1.py
index 313a534..8e09732 100644
--- a/src/pinnwand/handler/api_v1.py
+++ b/src/pinnwand/handler/api_v1.py
@@ -1,6 +1,6 @@
 import json
 import logging
-from datetime import timedelta
+from datetime import datetime, timedelta
 from typing import Any
 from urllib.parse import urljoin
 
@@ -122,3 +122,42 @@ async def post(self) -> None:
             url_removal = urljoin(url_request, f"/remove/{paste.removal}")
 
             self.write({"link": url_paste, "removal": url_removal})
+
+
+class PasteDetail(Base):
+    async def get(self, slug: str) -> None:
+        if defensive.ratelimit(self.request, area="read"):
+            raise error.RatelimitError()
+
+        with database.session() as session:
+            paste = (
+                session.query(database.Paste)
+                .filter(database.Paste.slug == slug)
+                .first()
+            )
+
+            if not paste:
+                raise tornado.web.HTTPError(404)
+
+            if paste.exp_date < datetime.utcnow():
+                session.delete(paste)
+                session.commit()
+
+                log.warn(
+                    "Show.get: paste was expired, is your cronjob running?"
+                )
+
+                raise tornado.web.HTTPError(404)
+
+            self.write(
+                {
+                    "files": [
+                        {
+                            "name": file.filename,
+                            "lexer": file.lexer,
+                            "content": file.raw,
+                        }
+                        for file in paste.files
+                    ],
+                }
+            )
diff --git a/src/pinnwand/http.py b/src/pinnwand/http.py
index fa505b9..d5a811f 100644
--- a/src/pinnwand/http.py
+++ b/src/pinnwand/http.py
@@ -44,6 +44,7 @@ def make_application(debug: bool = False) -> tornado.web.Application:
 
     pages += [
         (r"/api/v1/paste", handler.api_v1.Paste),
+        (r"/api/v1/paste/([A-Z2-7]+)(?:#.+)?", handler.api_v1.PasteDetail),
         (r"/api/v1/lexer", handler.api_v1.Lexer),
         (r"/api/v1/expiry", handler.api_v1.Expiry),
         (r"/json/new", handler.api_deprecated.Create),


Test patch:
diff --git a/test/integration/test_http_api.py b/test/integration/test_http_api.py
index e9b0b9e..9b8df48 100644
--- a/test/integration/test_http_api.py
+++ b/test/integration/test_http_api.py
@@ -481,3 +481,41 @@ def test_api_new_many_file_large(self) -> None:
     def test_api_new_wrong_method(self) -> None:
         response = self.fetch("/api/v1/paste")
         assert response.code == 405
+
+
+    def test_api_detail_many_files(self) -> None:
+        response = self.fetch(
+            "/api/v1/paste",
+            method="POST",
+            body=json.dumps(
+                {
+                    "expiry": "1day",
+                    "files": [
+                        {
+                            "name": "spam",
+                            "content": "a",
+                            "lexer": "c",
+                        },
+                    ]
+                    * 128,
+                }
+            ),
+        )
+
+        assert response.code == 200
+
+        data = json.loads(response.body)
+        name = data["link"].split("/")[-1]
+
+        response = self.fetch(
+            f"/api/v1/paste/{name}",
+            method="GET",
+        )
+
+        assert response.code == 200
+        data = json.loads(response.body)
+
+        assert len(data["files"]) == 128
+        assert data["files"][0]["name"] == "spam"
+        assert data["files"][0]["content"] == "a"
+        assert data["files"][0]["lexer"] == "c"