Skip to content

Notes API

reptor.api.NotesAPI.NotesAPI

API client for interacting with SysReptor project notes or personal notes.

Example
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from reptor import Reptor

reptor = Reptor(
    server=os.environ.get("REPTOR_SERVER"),
    token=os.environ.get("REPTOR_TOKEN"),
    personal_notes=False,
)

# NotesAPI is available as reptor.api.notes, e.g.:
reptor.api.notes.get_notes()
Source code in reptor/api/NotesAPI.py
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
class NotesAPI(APIClient):
    """API client for interacting with SysReptor project notes or personal notes.

    Example:
        ```python
        from reptor import Reptor

        reptor = Reptor(
            server=os.environ.get("REPTOR_SERVER"),
            token=os.environ.get("REPTOR_TOKEN"),
            personal_notes=False,
        )

        # NotesAPI is available as reptor.api.notes, e.g.:
        reptor.api.notes.get_notes()
        ```
    """

    def __init__(self, **kwargs) -> None:
        super().__init__(require_project_id=False, **kwargs)

        if self.personal_note:
            self.base_endpoint = urljoin(
                self.reptor.get_config().get_server(),
                "api/v1/pentestusers/self/notes/",
            )
        elif self.project_id:
            self.base_endpoint = urljoin(
                self.reptor.get_config().get_server(),
                f"api/v1/pentestprojects/{self.project_id}/notes/",
            )

    @property
    def personal_note(self):
        return self.reptor.get_config().get("personal_note")

    def get_notes(self) -> typing.List[Note]:
        """Gets list of all notes in the current context (project notes or personal notes).

        Returns:
            List of notes for this project or user

        Example:
            ```python
            reptor.api.notes.get_notes()
            ```
        """
        response = self.get(self.base_endpoint)
        notes = list()
        for note_data in response.json():
            notes.append(Note(note_data))
        return notes

    def get_note(
        self,
        id: typing.Optional[str] = None,
        title: typing.Optional[str] = None,
    ) -> typing.Optional[Note]:
        """Gets a single note by ID or title.

        Args:
            id (str, optional): Note ID to retrieve (prioritized over title)
            title (str, optional): Note title to search for

        Returns:
            Note object if found, None otherwise

        Example:
            ```python
            # Get note by ID
            note = reptor.api.notes.get_note(id="983a7e95-b2d9-4d57-984e-08496264cce8")

            # Get note by title
            note = reptor.api.notes.get_note(title="My Note")
            ```
        """
        for note in self.get_notes():
            if id:
                if note.id == id:
                    return note
            elif title:
                if note.title == title:
                    return note
            else:
                raise ValueError("Either id or title must be provided")

    def create_note(
        self,
        title="Note by reptor",
        text=None,
        parent: typing.Optional[str] = None,
        order=None,
        checked=None,
        icon=None,
    ) -> Note:
        """Creates a new note.

        Args:
            title (str, optional): Note title. Defaults to "Note by reptor".
            text (str, optional): Note content. Defaults to None.
            parent (str, optional): Parent note ID for nested notes. Defaults to None.
            order (int, optional): Sort order for the note. Defaults to None.
            checked (bool, optional): Checkbox state for checklist notes. Defaults to None.
            icon (str, optional): Emoji icon for the note. Defaults to None.

        Returns:
            Created note object

        Example:
            ```python
            reptor.api.notes.create_note(
                title="My New Note",
                text="This is the content",
                icon="📝"
            )
            ```
        """
        if title is None:
            raise ValueError("Note title must not be null.")
        note = self.post(
            self.base_endpoint,
            json={
                "order": order,
                "parent": parent or None,
                "checked": checked,
                "title": title,
                "text": text or "",
            },
        ).json()
        if icon:
            self.set_icon(note.get("id"), icon)
        elif title == "Uploads":
            self.set_icon(note.get("id"), "📤")
        return Note(note)

    def write_note(
        self,
        id: str = None,
        title: str = None,
        text: str = "",
        checked: bool = None,
        icon_emoji: str = None,
        order: int = 0,
        timestamp: bool = False,
        **kwargs,
    ):
        """Updates notes, appends text to a note.

        Args:
            id (str, optional): Note ID to update
            title (str, optional): Note title.
            text (str, optional): Append text to the note. Defaults to empty string.
            timestamp (bool, optional): Prepend timestamp to newly inserted text. Defaults to False.
            checked (bool, optional): Checkbox state for checklist notes.
            icon_emoji (str, optional): Emoji icon for the note.
            order (int, optional): Sort order for the note. Defaults to 0.

        Example:
            ```python
            reptor.api.notes.write_note(
                title="Security Finding",
                text="Found vulnerability in authentication",
                timestamp=True
            )
            ```
        """
        note_template = NoteTemplate.from_kwargs(
            id=id, 
            title=title, 
            text=text, 
            checked=checked, 
            icon_emoji=icon_emoji, 
            order=order,
            **kwargs
        )
        self.write_note_templates(
            note_template, timestamp=timestamp
        )

    def write_note_templates(
        self,
        note_templates: typing.Union[NoteTemplate, typing.List[NoteTemplate]],
        timestamp: bool = True,
        **kwargs,
    ):
        if not isinstance(note_templates, list):
            note_templates = [note_templates]
        for note_template in note_templates:
            if note_template.id:
                new_note = False
                note = self.get_note(id=note_template.id)
                if not note:
                    raise ValueError(f'Note with ID "{note_template.id}" does not exist.')
            else:
                if note_template.parent_title and not note_template.parent:
                    note_template.parent = self.get_or_create_note_by_title(
                        note_template.parent_title
                    ).id

                note = None
                if not note_template.force_new:
                    note = self.get_note_by_title(
                        note_template.title,
                        parent=note_template.parent,
                    )
                if note is None:
                    new_note = True
                    note = self.create_note(
                        title=note_template.title,
                        parent=note_template.parent or None,
                    )
                else:
                    new_note = False
            self.debug(f"Got note from server {note.title} ({note.id})")

            # Prepare note (append content to existing note, etc)
            note_text = note.text + "\n\n" if note.text else ""
            if (
                timestamp and note_template.text
            ):  # Only add timestamp if there is content
                note_text += f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]"
                if "\n" in note_template.text:
                    if not note_template.text.startswith("\n"):
                        note_text += "\n"
                else:
                    note_text += ": "
            note_text += note_template.text or ""

            if new_note:
                upload_note = Note.from_note_template(note_template)
                upload_note.parent = note.parent
                upload_note.id = note.id
                upload_note.text = note_text
            else:
                upload_note = note
                if note_template.title:
                    upload_note.title = note_template.title
                if note_template.checked is not None:
                    upload_note.checked = note_template.checked
                if note_template.icon_emoji:
                    upload_note.icon_emoji = note_template.icon_emoji
                if note_template.order:
                    upload_note.order = note_template.order
                upload_note.text = note_text

            # Upload note and children recursively
            self._upload_note(upload_note, **kwargs)
            for child in note_template.children:
                child.parent = note.id
                self.write_note_templates(child, timestamp=timestamp, **kwargs)

    def set_icon(self, id: str, icon: str):
        """Sets an emoji icon for a note.

        Args:
            id (str): Note ID
            icon (str): Emoji character to set as icon

        Example:
            ```python
            reptor.api.notes.set_icon("983a7e95-b2d9-4d57-984e-08496264cce8", "🔒")
            ```
        """
        url = urljoin(self.base_endpoint, f"{id}/")
        self.put(url, json={"icon_emoji": icon})

    def upload_file(
        self,
        file: typing.Optional[typing.IO] = None,
        content: typing.Optional[bytes] = None,
        filename: typing.Optional[str] = None,
        caption: typing.Optional[str] = None,
        note_id: typing.Optional[str] = None,
        note_title: typing.Optional[str] = None,
        parent_title: typing.Optional[str] = None,
        **kwargs,
    ):
        """Uploads a file to a note.

        Args:
            file (typing.IO, optional): File object to upload
            content (bytes, optional): File content as bytes
            filename (str, optional): Name for the uploaded file
            caption (str, optional): Caption for the file link
            note_id (str, optional): ID of note to upload to
            note_title (str, optional): Title of note to upload to
            parent_title (str, optional): Parent note title for organization
            **kwargs: Additional parameters for note writing

        Example:
            ```python
            # Upload from file
            with open("screenshot.png", "rb") as f:
                reptor.api.notes.upload_file(
                    file=f,
                    note_title="Evidence",
                    caption="Login page screenshot"
                )

            # Upload from bytes
            reptor.api.notes.upload_file(
                content=b"file content",
                filename="data.txt",
                note_title="Files"
            )
            ```
        """
        assert file or content
        assert not (file and content)

        if file:
            if file.name == "<stdin>":
                self.display("Reading from stdin...")
            elif not filename:
                filename = basename(file.name)
            # TODO this might be streamed to not load entire file to memory
            try:
                content = file.buffer.read()  # type: ignore
            except AttributeError:
                content = file.read()
            if not filename:
                filetype = guess_filetype(content) or "dat"
                filename = f"data.{filetype}"

            if not content:
                self.warning(f"{file.name} is empty. Will not upload.")
                return

        if not note_id:
            note_id = self.get_or_create_note_by_title(
                note_title or "Uploads", parent_title=parent_title
            ).id
        if self.personal_note:
            url = urljoin(self.base_endpoint, "upload/")
        else:
            url = urljoin(self.base_endpoint.rsplit("/", 2)[0], "upload/")
        response_json = self.post(
            url, files={"file": (filename, content)}, json_content=False
        ).json()
        is_image = True if response_json.get("resource_type") == "image" else False
        if is_image:
            file_path = f"/images/name/{response_json['name']}"
            note_content = f"\n![{caption or filename}]({file_path})"
        else:
            file_path = f"/files/name/{response_json['name']}"
            note_content = f"\n[{caption or filename}]({file_path})"

        self.write_note(
            id=note_id,
            text=note_content,
            **kwargs,
        )

    def render(
        self,
        id: str,
    ) -> bytes:
        """Renders a note to PDF format.

        Args:
            id (str): Note ID to render

        Returns:
            PDF content as bytes

        Example:
            ```python
            pdf_data = reptor.api.notes.render("note-uuid-here")
            with open("note.pdf", "wb") as f:
                f.write(pdf_data)
            ```
        """
        url = urljoin(self.base_endpoint, f"{id}/export-pdf/")
        response = self.post(url)
        response.raise_for_status()
        return response.content

    def delete_note(self, id: str):
        """Deletes a note by ID.

        Args:
            id (str): Note ID to delete

        Example:
            ```python
            reptor.api.notes.delete_note("983a7e95-b2d9-4d57-984e-08496264cce8")
            ```
        """
        url = urljoin(self.base_endpoint, f"{id}/")
        self.delete(url)

    def duplicate(
        self,
        id: str,
    ) -> Note:
        """Creates a note duplicate.

        Args:
            id (str): Note ID to duplicate

        Returns:
            Duplicated note object

        Example:
            ```python
            duplicate_note = reptor.api.notes.duplicate("note-uuid-here")
            print(f"Duplicated note: {duplicate_note.title}")
            ```
        """
        url = urljoin(self.base_endpoint, f"{id}/copy/")
        response = self.post(url)
        response.raise_for_status()
        return Note(response.json())

    def get_note_by_title(
        self,
        title,
        parent=None,  # Preferred over parent_title
        parent_title=None,
        any_parent=False,
    ) -> typing.Optional[Note]:
        if not parent and parent_title:
            try:
                parent = self.get_note_by_title(parent_title, any_parent=True).id  # type: ignore
            except AttributeError:
                raise ValueError(f'Parent note "{parent_title}" does not exist.')
        notes_list = self.get_notes()

        for note in notes_list:
            if note.title == title and (note.parent == parent or any_parent):
                break
        else:
            return None
        return note

    def get_or_create_note_by_title(
        self,
        title,
        parent=None,  # Preferred over parent_title
        parent_title=None,
        icon=None,
    ) -> Note:
        if not parent and parent_title:
            parent = self.get_or_create_note_by_title(
                parent_title, icon=icon
            ).id
        note = self.get_note_by_title(title, parent=parent)
        if not note:
            # Note does not exist. Create.
            note = self.create_note(title=title, parent=parent, icon=icon)
        return note

    def _upload_note(
        self,
        note: Note,
    ):
        url = urljoin(self.base_endpoint, note.id, "")
        r = self.put(url, json=note.to_dict())

        try:
            r.raise_for_status()
            self.display(f'Note written to "{note.title}".')
        except HTTPError as e:
            raise HTTPError(
                f'{str(e)} Are you uploading binary content to note? (Try "file" subcommand)'
            ) from e

get_notes

get_notes()

Gets list of all notes in the current context (project notes or personal notes).

Returns:

  • List[Note]

    List of notes for this project or user

Example
1
reptor.api.notes.get_notes()
Source code in reptor/api/NotesAPI.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
def get_notes(self) -> typing.List[Note]:
    """Gets list of all notes in the current context (project notes or personal notes).

    Returns:
        List of notes for this project or user

    Example:
        ```python
        reptor.api.notes.get_notes()
        ```
    """
    response = self.get(self.base_endpoint)
    notes = list()
    for note_data in response.json():
        notes.append(Note(note_data))
    return notes

get_note

get_note(id=None, title=None)

Gets a single note by ID or title.

Parameters:

  • id (str, default: None ) –

    Note ID to retrieve (prioritized over title)

  • title (str, default: None ) –

    Note title to search for

Returns:

  • Optional[Note]

    Note object if found, None otherwise

Example
1
2
3
4
5
# Get note by ID
note = reptor.api.notes.get_note(id="983a7e95-b2d9-4d57-984e-08496264cce8")

# Get note by title
note = reptor.api.notes.get_note(title="My Note")
Source code in reptor/api/NotesAPI.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
def get_note(
    self,
    id: typing.Optional[str] = None,
    title: typing.Optional[str] = None,
) -> typing.Optional[Note]:
    """Gets a single note by ID or title.

    Args:
        id (str, optional): Note ID to retrieve (prioritized over title)
        title (str, optional): Note title to search for

    Returns:
        Note object if found, None otherwise

    Example:
        ```python
        # Get note by ID
        note = reptor.api.notes.get_note(id="983a7e95-b2d9-4d57-984e-08496264cce8")

        # Get note by title
        note = reptor.api.notes.get_note(title="My Note")
        ```
    """
    for note in self.get_notes():
        if id:
            if note.id == id:
                return note
        elif title:
            if note.title == title:
                return note
        else:
            raise ValueError("Either id or title must be provided")

create_note

create_note(title='Note by reptor', text=None, parent=None, order=None, checked=None, icon=None)

Creates a new note.

Parameters:

  • title (str, default: 'Note by reptor' ) –

    Note title. Defaults to "Note by reptor".

  • text (str, default: None ) –

    Note content. Defaults to None.

  • parent (str, default: None ) –

    Parent note ID for nested notes. Defaults to None.

  • order (int, default: None ) –

    Sort order for the note. Defaults to None.

  • checked (bool, default: None ) –

    Checkbox state for checklist notes. Defaults to None.

  • icon (str, default: None ) –

    Emoji icon for the note. Defaults to None.

Returns:

  • Note

    Created note object

Example
1
2
3
4
5
reptor.api.notes.create_note(
    title="My New Note",
    text="This is the content",
    icon="📝"
)
Source code in reptor/api/NotesAPI.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
def create_note(
    self,
    title="Note by reptor",
    text=None,
    parent: typing.Optional[str] = None,
    order=None,
    checked=None,
    icon=None,
) -> Note:
    """Creates a new note.

    Args:
        title (str, optional): Note title. Defaults to "Note by reptor".
        text (str, optional): Note content. Defaults to None.
        parent (str, optional): Parent note ID for nested notes. Defaults to None.
        order (int, optional): Sort order for the note. Defaults to None.
        checked (bool, optional): Checkbox state for checklist notes. Defaults to None.
        icon (str, optional): Emoji icon for the note. Defaults to None.

    Returns:
        Created note object

    Example:
        ```python
        reptor.api.notes.create_note(
            title="My New Note",
            text="This is the content",
            icon="📝"
        )
        ```
    """
    if title is None:
        raise ValueError("Note title must not be null.")
    note = self.post(
        self.base_endpoint,
        json={
            "order": order,
            "parent": parent or None,
            "checked": checked,
            "title": title,
            "text": text or "",
        },
    ).json()
    if icon:
        self.set_icon(note.get("id"), icon)
    elif title == "Uploads":
        self.set_icon(note.get("id"), "📤")
    return Note(note)

write_note

write_note(id=None, title=None, text='', checked=None, icon_emoji=None, order=0, timestamp=False, **kwargs)

Updates notes, appends text to a note.

Parameters:

  • id (str, default: None ) –

    Note ID to update

  • title (str, default: None ) –

    Note title.

  • text (str, default: '' ) –

    Append text to the note. Defaults to empty string.

  • timestamp (bool, default: False ) –

    Prepend timestamp to newly inserted text. Defaults to False.

  • checked (bool, default: None ) –

    Checkbox state for checklist notes.

  • icon_emoji (str, default: None ) –

    Emoji icon for the note.

  • order (int, default: 0 ) –

    Sort order for the note. Defaults to 0.

Example
1
2
3
4
5
reptor.api.notes.write_note(
    title="Security Finding",
    text="Found vulnerability in authentication",
    timestamp=True
)
Source code in reptor/api/NotesAPI.py
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
def write_note(
    self,
    id: str = None,
    title: str = None,
    text: str = "",
    checked: bool = None,
    icon_emoji: str = None,
    order: int = 0,
    timestamp: bool = False,
    **kwargs,
):
    """Updates notes, appends text to a note.

    Args:
        id (str, optional): Note ID to update
        title (str, optional): Note title.
        text (str, optional): Append text to the note. Defaults to empty string.
        timestamp (bool, optional): Prepend timestamp to newly inserted text. Defaults to False.
        checked (bool, optional): Checkbox state for checklist notes.
        icon_emoji (str, optional): Emoji icon for the note.
        order (int, optional): Sort order for the note. Defaults to 0.

    Example:
        ```python
        reptor.api.notes.write_note(
            title="Security Finding",
            text="Found vulnerability in authentication",
            timestamp=True
        )
        ```
    """
    note_template = NoteTemplate.from_kwargs(
        id=id, 
        title=title, 
        text=text, 
        checked=checked, 
        icon_emoji=icon_emoji, 
        order=order,
        **kwargs
    )
    self.write_note_templates(
        note_template, timestamp=timestamp
    )

set_icon

set_icon(id, icon)

Sets an emoji icon for a note.

Parameters:

  • id (str) –

    Note ID

  • icon (str) –

    Emoji character to set as icon

Example
1
reptor.api.notes.set_icon("983a7e95-b2d9-4d57-984e-08496264cce8", "🔒")
Source code in reptor/api/NotesAPI.py
266
267
268
269
270
271
272
273
274
275
276
277
278
279
def set_icon(self, id: str, icon: str):
    """Sets an emoji icon for a note.

    Args:
        id (str): Note ID
        icon (str): Emoji character to set as icon

    Example:
        ```python
        reptor.api.notes.set_icon("983a7e95-b2d9-4d57-984e-08496264cce8", "🔒")
        ```
    """
    url = urljoin(self.base_endpoint, f"{id}/")
    self.put(url, json={"icon_emoji": icon})

upload_file

upload_file(file=None, content=None, filename=None, caption=None, note_id=None, note_title=None, parent_title=None, **kwargs)

Uploads a file to a note.

Parameters:

  • file (IO, default: None ) –

    File object to upload

  • content (bytes, default: None ) –

    File content as bytes

  • filename (str, default: None ) –

    Name for the uploaded file

  • caption (str, default: None ) –

    Caption for the file link

  • note_id (str, default: None ) –

    ID of note to upload to

  • note_title (str, default: None ) –

    Title of note to upload to

  • parent_title (str, default: None ) –

    Parent note title for organization

  • **kwargs

    Additional parameters for note writing

Example
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Upload from file
with open("screenshot.png", "rb") as f:
    reptor.api.notes.upload_file(
        file=f,
        note_title="Evidence",
        caption="Login page screenshot"
    )

# Upload from bytes
reptor.api.notes.upload_file(
    content=b"file content",
    filename="data.txt",
    note_title="Files"
)
Source code in reptor/api/NotesAPI.py
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
def upload_file(
    self,
    file: typing.Optional[typing.IO] = None,
    content: typing.Optional[bytes] = None,
    filename: typing.Optional[str] = None,
    caption: typing.Optional[str] = None,
    note_id: typing.Optional[str] = None,
    note_title: typing.Optional[str] = None,
    parent_title: typing.Optional[str] = None,
    **kwargs,
):
    """Uploads a file to a note.

    Args:
        file (typing.IO, optional): File object to upload
        content (bytes, optional): File content as bytes
        filename (str, optional): Name for the uploaded file
        caption (str, optional): Caption for the file link
        note_id (str, optional): ID of note to upload to
        note_title (str, optional): Title of note to upload to
        parent_title (str, optional): Parent note title for organization
        **kwargs: Additional parameters for note writing

    Example:
        ```python
        # Upload from file
        with open("screenshot.png", "rb") as f:
            reptor.api.notes.upload_file(
                file=f,
                note_title="Evidence",
                caption="Login page screenshot"
            )

        # Upload from bytes
        reptor.api.notes.upload_file(
            content=b"file content",
            filename="data.txt",
            note_title="Files"
        )
        ```
    """
    assert file or content
    assert not (file and content)

    if file:
        if file.name == "<stdin>":
            self.display("Reading from stdin...")
        elif not filename:
            filename = basename(file.name)
        # TODO this might be streamed to not load entire file to memory
        try:
            content = file.buffer.read()  # type: ignore
        except AttributeError:
            content = file.read()
        if not filename:
            filetype = guess_filetype(content) or "dat"
            filename = f"data.{filetype}"

        if not content:
            self.warning(f"{file.name} is empty. Will not upload.")
            return

    if not note_id:
        note_id = self.get_or_create_note_by_title(
            note_title or "Uploads", parent_title=parent_title
        ).id
    if self.personal_note:
        url = urljoin(self.base_endpoint, "upload/")
    else:
        url = urljoin(self.base_endpoint.rsplit("/", 2)[0], "upload/")
    response_json = self.post(
        url, files={"file": (filename, content)}, json_content=False
    ).json()
    is_image = True if response_json.get("resource_type") == "image" else False
    if is_image:
        file_path = f"/images/name/{response_json['name']}"
        note_content = f"\n![{caption or filename}]({file_path})"
    else:
        file_path = f"/files/name/{response_json['name']}"
        note_content = f"\n[{caption or filename}]({file_path})"

    self.write_note(
        id=note_id,
        text=note_content,
        **kwargs,
    )

render

render(id)

Renders a note to PDF format.

Parameters:

  • id (str) –

    Note ID to render

Returns:

  • bytes

    PDF content as bytes

Example
1
2
3
pdf_data = reptor.api.notes.render("note-uuid-here")
with open("note.pdf", "wb") as f:
    f.write(pdf_data)
Source code in reptor/api/NotesAPI.py
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
def render(
    self,
    id: str,
) -> bytes:
    """Renders a note to PDF format.

    Args:
        id (str): Note ID to render

    Returns:
        PDF content as bytes

    Example:
        ```python
        pdf_data = reptor.api.notes.render("note-uuid-here")
        with open("note.pdf", "wb") as f:
            f.write(pdf_data)
        ```
    """
    url = urljoin(self.base_endpoint, f"{id}/export-pdf/")
    response = self.post(url)
    response.raise_for_status()
    return response.content

delete_note

delete_note(id)

Deletes a note by ID.

Parameters:

  • id (str) –

    Note ID to delete

Example
1
reptor.api.notes.delete_note("983a7e95-b2d9-4d57-984e-08496264cce8")
Source code in reptor/api/NotesAPI.py
392
393
394
395
396
397
398
399
400
401
402
403
404
def delete_note(self, id: str):
    """Deletes a note by ID.

    Args:
        id (str): Note ID to delete

    Example:
        ```python
        reptor.api.notes.delete_note("983a7e95-b2d9-4d57-984e-08496264cce8")
        ```
    """
    url = urljoin(self.base_endpoint, f"{id}/")
    self.delete(url)

duplicate

duplicate(id)

Creates a note duplicate.

Parameters:

  • id (str) –

    Note ID to duplicate

Returns:

  • Note

    Duplicated note object

Example
1
2
duplicate_note = reptor.api.notes.duplicate("note-uuid-here")
print(f"Duplicated note: {duplicate_note.title}")
Source code in reptor/api/NotesAPI.py
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
def duplicate(
    self,
    id: str,
) -> Note:
    """Creates a note duplicate.

    Args:
        id (str): Note ID to duplicate

    Returns:
        Duplicated note object

    Example:
        ```python
        duplicate_note = reptor.api.notes.duplicate("note-uuid-here")
        print(f"Duplicated note: {duplicate_note.title}")
        ```
    """
    url = urljoin(self.base_endpoint, f"{id}/copy/")
    response = self.post(url)
    response.raise_for_status()
    return Note(response.json())