36
36
from . import __version__ , __author__ , __contact__ , __url__
37
37
from .schema import PasteCreate , PasteResponse , PasteDetails
38
38
39
- description : str = "paste.py 🐍 - A pastebin written in python."
39
+ DESCRIPTION : str = "paste.py 🐍 - A pastebin written in python."
40
40
41
41
limiter = Limiter (key_func = get_remote_address )
42
42
app : FastAPI = FastAPI (
54
54
app .state .limiter = limiter
55
55
56
56
57
- def rate_limit_exceeded_handler (request : Request , exc : Exception ) -> Union [Response , Awaitable [Response ]]:
57
+ def rate_limit_exceeded_handler (
58
+ request : Request , exc : Exception
59
+ ) -> Union [Response , Awaitable [Response ]]:
58
60
if isinstance (exc , RateLimitExceeded ):
59
- return Response (
60
- content = "Rate limit exceeded" ,
61
- status_code = 429
62
- )
63
- return Response (
64
- content = "An error occurred" ,
65
- status_code = 500
66
- )
61
+ return Response (content = "Rate limit exceeded" , status_code = 429 )
62
+ return Response (content = "An error occurred" , status_code = 500 )
63
+
67
64
68
65
app .add_exception_handler (RateLimitExceeded , rate_limit_exceeded_handler )
69
66
@@ -84,13 +81,14 @@ def rate_limit_exceeded_handler(request: Request, exc: Exception) -> Union[Respo
84
81
85
82
BASE_DIR : Path = Path (__file__ ).resolve ().parent
86
83
87
- templates : Jinja2Templates = Jinja2Templates (
88
- directory = str (Path (BASE_DIR , "templates" )))
84
+ templates : Jinja2Templates = Jinja2Templates (directory = str (Path (BASE_DIR , "templates" )))
89
85
90
86
91
87
@app .post ("/file" )
92
88
@limiter .limit ("100/minute" )
93
- async def post_as_a_file (request : Request , file : UploadFile = File (...)) -> PlainTextResponse :
89
+ async def post_as_a_file (
90
+ request : Request , file : UploadFile = File (...)
91
+ ) -> PlainTextResponse :
94
92
try :
95
93
uuid : str = generate_uuid ()
96
94
if uuid in large_uuid_storage :
@@ -119,7 +117,9 @@ async def post_as_a_file(request: Request, file: UploadFile = File(...)) -> Plai
119
117
120
118
121
119
@app .get ("/paste/{uuid}" )
122
- async def get_paste_data (uuid : str , user_agent : Optional [str ] = Header (None )) -> Response :
120
+ async def get_paste_data (
121
+ request : Request , uuid : str , user_agent : Optional [str ] = Header (None )
122
+ ) -> Response :
123
123
if not "." in uuid :
124
124
uuid = _find_without_extension (uuid )
125
125
path : str = f"data/{ uuid } "
@@ -143,104 +143,26 @@ async def get_paste_data(uuid: str, user_agent: Optional[str] = Header(None)) ->
143
143
try :
144
144
lexer = get_lexer_by_name (file_extension , stripall = True )
145
145
except ClassNotFound :
146
- lexer = get_lexer_by_name (
147
- "text" , stripall = True ) # Default lexer
146
+ lexer = get_lexer_by_name ("text" , stripall = True ) # Default lexer
147
+
148
148
formatter = HtmlFormatter (
149
- style = "colorful" , full = True , linenos = "inline" , cssclass = "code" )
149
+ style = "monokai" , # Dark theme base
150
+ linenos = "inline" ,
151
+ cssclass = "highlight" ,
152
+ nowrap = False ,
153
+ )
154
+
150
155
highlighted_code : str = highlight (content , lexer , formatter )
151
- # print(highlighted_code)
152
- custom_style = """
153
- .code pre span.linenos {
154
- color: #999;
155
- padding-right: 10px;
156
- -webkit-user-select: none;
157
- -webkit-touch-callout: none;
158
- -moz-user-select: none;
159
- -ms-user-select: none;
160
- user-select: none;
161
- }
162
-
163
- span {
164
- font-size: 1.1em !important;
165
- }
166
-
167
- pre {
168
- line-height: 1.4 !important;
169
- }
170
-
171
- .code pre span.linenos::after {
172
- content: "";
173
- border-right: 1px solid #999;
174
- height: 100%;
175
- margin-left: 10px;
176
- }
177
-
178
- .code {
179
- background-color: #fff;
180
- border: 1.5px solid #ddd;
181
- border-radius: 5px;
182
- margin-bottom: 20px;
183
- overflow: auto;
184
- }
185
-
186
- pre {
187
- font-family: 'Consolas','Monaco','Andale Mono','Ubuntu Mono','monospace;' !important;
188
- }
189
- .copy-button {
190
- position: fixed;
191
- top: 10px;
192
- right: 10px;
193
- padding: 10px;
194
- background-color: #4CAF50;
195
- color: #fff;
196
- cursor: pointer;
197
- border: none;
198
- border-radius: 5px;
199
- outline: none;
200
- }
201
- """
202
- custom_script = """
203
- function copyAllText() {
204
- // Create a range object to select the entire document
205
- const range = document.createRange();
206
- range.selectNode(document.body);
207
-
208
- // Create a selection object and add the range to it
209
- const selection = window.getSelection();
210
- selection.removeAllRanges();
211
- selection.addRange(range);
212
-
213
- // Copy the selected text to the clipboard
214
- document.execCommand('copy');
215
-
216
- // Clear the selection to avoid interfering with the user's selection
217
- selection.removeAllRanges();
218
-
219
- // You can customize the copied message
220
- alert('All text copied to clipboard!');
221
- }
222
-
223
- """
224
- response_content : str = f"""
225
- <html>
226
- <head>
227
- <title>{ uuid } | paste.py 🐍</title>
228
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
229
- <style>{ custom_style } </style>
230
- <style>{ formatter .get_style_defs ('.highlight' )} </style>
231
- </head>
232
- <body>
233
- <div id="copyButton" class="copy-button" onclick="copyAllText()">
234
- <i class="fas fa-copy"></i>
235
- </div>
236
- { highlighted_code }
237
- </body>
238
- <script>
239
- { custom_script }
240
- </script>
241
- </html>
242
- """
243
- return HTMLResponse (content = response_content )
156
+
157
+ return templates .TemplateResponse (
158
+ "paste.html" ,
159
+ {
160
+ "request" : request ,
161
+ "uuid" : uuid ,
162
+ "highlighted_code" : highlighted_code ,
163
+ "pygments_css" : formatter .get_style_defs (".highlight" ),
164
+ },
165
+ )
244
166
except Exception :
245
167
raise HTTPException (
246
168
detail = "404: The Requested Resource is not found" ,
@@ -261,11 +183,13 @@ async def delete_paste(uuid: str) -> PlainTextResponse:
261
183
os .remove (path )
262
184
return PlainTextResponse (f"File successfully deleted { uuid } " )
263
185
except FileNotFoundError :
264
- raise HTTPException (detail = "File Not Found" ,
265
- status_code = status .HTTP_404_NOT_FOUND )
186
+ raise HTTPException (
187
+ detail = "File Not Found" , status_code = status .HTTP_404_NOT_FOUND
188
+ )
266
189
except Exception as e :
267
190
raise HTTPException (
268
- detail = f"The exception is { e } " , status_code = status .HTTP_409_CONFLICT )
191
+ detail = f"The exception is { e } " , status_code = status .HTTP_409_CONFLICT
192
+ )
269
193
270
194
271
195
@app .get ("/web" , response_class = HTMLResponse )
@@ -276,8 +200,9 @@ async def web(request: Request) -> Response:
276
200
277
201
@app .post ("/web" , response_class = PlainTextResponse )
278
202
@limiter .limit ("100/minute" )
279
- async def web_post (request : Request , content : str = Form (...),
280
- extension : Optional [str ] = Form (None )) -> RedirectResponse :
203
+ async def web_post (
204
+ request : Request , content : str = Form (...), extension : Optional [str ] = Form (None )
205
+ ) -> RedirectResponse :
281
206
try :
282
207
file_content : bytes = content .encode ()
283
208
uuid : str = generate_uuid ()
@@ -297,7 +222,9 @@ async def web_post(request: Request, content: str = Form(...),
297
222
status_code = status .HTTP_403_FORBIDDEN ,
298
223
)
299
224
300
- return RedirectResponse (f"{ BASE_URL } /paste/{ uuid_ } " , status_code = status .HTTP_303_SEE_OTHER )
225
+ return RedirectResponse (
226
+ f"{ BASE_URL } /paste/{ uuid_ } " , status_code = status .HTTP_303_SEE_OTHER
227
+ )
301
228
302
229
303
230
@app .get ("/health" , status_code = status .HTTP_200_OK )
@@ -322,54 +249,53 @@ async def get_languages() -> JSONResponse:
322
249
status_code = status .HTTP_500_INTERNAL_SERVER_ERROR ,
323
250
)
324
251
252
+
325
253
# apis to create and get a paste which returns uuid and url (to be used by SDK)
326
254
@app .post ("/api/paste" , response_model = PasteResponse )
327
255
async def create_paste (paste : PasteCreate ) -> JSONResponse :
328
256
try :
329
257
uuid : str = generate_uuid ()
330
258
if uuid in large_uuid_storage :
331
259
uuid = generate_uuid ()
332
-
260
+
333
261
uuid_with_extension : str = f"{ uuid } .{ paste .extension } "
334
262
path : str = f"data/{ uuid_with_extension } "
335
-
263
+
336
264
with open (path , "w" , encoding = "utf-8" ) as f :
337
265
f .write (paste .content )
338
-
266
+
339
267
large_uuid_storage .append (uuid_with_extension )
340
-
268
+
341
269
return JSONResponse (
342
270
content = PasteResponse (
343
- uuid = uuid_with_extension ,
344
- url = f"{ BASE_URL } /paste/{ uuid_with_extension } "
271
+ uuid = uuid_with_extension , url = f"{ BASE_URL } /paste/{ uuid_with_extension } "
345
272
).dict (),
346
- status_code = status .HTTP_201_CREATED
273
+ status_code = status .HTTP_201_CREATED ,
347
274
)
348
275
except Exception as e :
349
276
raise HTTPException (
350
277
detail = f"There was an error creating the paste: { str (e )} " ,
351
278
status_code = status .HTTP_500_INTERNAL_SERVER_ERROR ,
352
279
)
353
280
281
+
354
282
@app .get ("/api/paste/{uuid}" , response_model = PasteDetails )
355
283
async def get_paste_details (uuid : str ) -> JSONResponse :
356
284
if not "." in uuid :
357
285
uuid = _find_without_extension (uuid )
358
286
path : str = f"data/{ uuid } "
359
-
287
+
360
288
try :
361
289
with open (path , "r" , encoding = "utf-8" ) as f :
362
290
content : str = f .read ()
363
-
291
+
364
292
extension : str = Path (path ).suffix [1 :]
365
-
293
+
366
294
return JSONResponse (
367
295
content = PasteDetails (
368
- uuid = uuid ,
369
- content = content ,
370
- extension = extension
296
+ uuid = uuid , content = content , extension = extension
371
297
).dict (),
372
- status_code = status .HTTP_200_OK
298
+ status_code = status .HTTP_200_OK ,
373
299
)
374
300
except FileNotFoundError :
375
301
raise HTTPException (
@@ -381,4 +307,3 @@ async def get_paste_details(uuid: str) -> JSONResponse:
381
307
detail = f"Error retrieving paste: { str (e )} " ,
382
308
status_code = status .HTTP_500_INTERNAL_SERVER_ERROR ,
383
309
)
384
-
0 commit comments