Metadata-Version: 2.1
Name: osintbuddy
Version: 0.0.4rc51.post1
Summary: OSINTBuddy - mine, merge, and map data for novel insights
Author-email: jerlendds <support@forum.osintbuddy.com>
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
Classifier: Programming Language :: Python :: 3.11
Requires-Dist: selenium>=4.9.0
Requires-Dist: sqlalchemy-json==0.7.0
Requires-Dist: SQLAlchemy-Utils==0.41.1
Requires-Dist: playwright>=1.39.0
Requires-Dist: httpx>=0.25.0
Requires-Dist: beautifulsoup4==4.12.2
Requires-Dist: pyfiglet==0.8.post1
Requires-Dist: termcolor==2.3.0
Requires-Dist: fastapi==0.103.2
Requires-Dist: uvicorn==0.22.0
Requires-Dist: uvloop==0.17.0
Requires-Dist: pydantic==2.4.2
Requires-Dist: pydantic-settings==2.0.3
Requires-Dist: yq==3.2.3
Requires-Dist: jedi-language-server==0.41.1
Requires-Dist: websockets==11.0.3
Requires-Dist: astroid==2.15.4 ; extra == "test"
Requires-Dist: colorama==0.4.6 ; extra == "test"
Requires-Dist: dill==0.3.6 ; extra == "test"
Requires-Dist: eradicate==2.2.0 ; extra == "test"
Requires-Dist: exceptiongroup==1.1.1 ; extra == "test"
Requires-Dist: iniconfig==2.0.0 ; extra == "test"
Requires-Dist: isort==5.12.0 ; extra == "test"
Requires-Dist: lazy-object-proxy==1.9.0 ; extra == "test"
Requires-Dist: mando==0.7.1 ; extra == "test"
Requires-Dist: mccabe==0.7.0 ; extra == "test"
Requires-Dist: mypy==1.3.0 ; extra == "test"
Requires-Dist: mypy-extensions==1.0.0 ; extra == "test"
Requires-Dist: packaging==23.1 ; extra == "test"
Requires-Dist: platformdirs==3.5.1 ; extra == "test"
Requires-Dist: pluggy==1.0.0 ; extra == "test"
Requires-Dist: pycodestyle==2.10.0 ; extra == "test"
Requires-Dist: pydocstyle==6.3.0 ; extra == "test"
Requires-Dist: pyflakes==3.0.1 ; extra == "test"
Requires-Dist: pylama==8.4.1 ; extra == "test"
Requires-Dist: pylint==2.17.4 ; extra == "test"
Requires-Dist: pytest==7.3.1 ; extra == "test"
Requires-Dist: radon==6.0.1 ; extra == "test"
Requires-Dist: six==1.16.0 ; extra == "test"
Requires-Dist: snowballstemmer==2.2.0 ; extra == "test"
Requires-Dist: toml==0.10.2 ; extra == "test"
Requires-Dist: tomli==2.0.1 ; extra == "test"
Requires-Dist: tomlkit==0.11.8 ; extra == "test"
Requires-Dist: typing-extensions==4.5.0 ; extra == "test"
Requires-Dist: vulture==2.7 ; extra == "test"
Requires-Dist: wrapt==1.15.0 ; extra == "test"
Project-URL: Documentation, https://docs.osintbuddy.com/
Project-URL: Source, https://github.com/jerlendds/osintbuddy-plugins
Project-URL: Tracker, https://github.com/jerlendds/osintbuddy/issues
Provides-Extra: test

# OSINTBuddy plugins and extensions

The plugins library for [jerlendds/osintbuddy](https://github.com/jerlendds/osintbuddy).


[2023-12-02_demo.webm](https://github.com/jerlendds/osintbuddy/assets/29207058/a7feba13-d1ca-43a0-ba25-b5c899eae89c)


***Please note:** [OSINTBuddy plugins](https://github.com/jerlendds/osintbuddy-plugins) are still in early alpha and breaking changes may occasionally occur in the API. That said, if you remain on the `main` branch and avoid accessing protected methods we will try our best to avoid introducing breaking changes.*

### **NOTICE:** There has been a major update to plugins, any created plugins will have to be updated to use the new, and more convenient data access method:
  - Remove `name` from any `ob.Plugin`
  - Update `node['data']` access to be `node.label_defined_in_node`
    - Please see the introduction to the plugin system below


The osintbuddy plugin system at its core is very simple. An `OBRegistry` class holds all registered `OBPlugin` classes within the application. This registry is loaded into the [osintbuddy application](https://github.com/jerlendds/osintbuddy/) where it is then used to load the available entities for the user when they access a project graph, load transforms when a user opens the context menu of a node, and perform transformations which expect a `Plugin.blueprint()` to be returned. The returned data of a transform decorated method will be automatically mapped to a [JanusGraph](https://janusgraph.org/) database through [gremlin](https://tinkerpop.apache.org/) according to the labels *(as snakecase)* you previously set in the classes `node` for whatever `Plugin.blueprint()`
you return.
 
To make this a bit more clear please see the below example...

```py
from pydantic import BaseModel
import osintbuddy import transform, Plugin
from osintbuddy.elements import TextInput, DropdownInput, Title, CopyText
from osintbuddy.errors import OBPluginError


class CSESearchResults(Plugin):
    label = "CSE Result"
    name = "CSE result"
    show_label = False  # do not show this on the entities dialog 
    # the user sees on the left of the project graph screen
    color = "#058F63"
    node = [
        Title(label="Result"),
        CopyText(label="URL"),
        CopyText(label="Cache URL"),
    ]


class CSESearchPlugin(Plugin):
    label = "CSE Search"
    name = "CSE search"
    color = "#2C7237"
    node = [
        [
            TextInput(label="Query", icon="search"),
            TextInput(label="Pages", icon="123", default="1"),
        ],
        DropdownInput(label="CSE Categories", options=cse_link_options)
    ]

    @transform(label="To cse results", icon="search")
    async def transform_to_cse_results(
      self,
      node: BaseModel,  # dynamically generated pydantic model 
      # that is mapped from the above labels contained within `node`
      use  # a pydantic model allowing you to access a selenium instance
      # (and eventually a gremlin graph and settings api) 
    ):
        results = []

        if not node.query:
          raise OBPluginError((
            'You can send error messages to the user here'
            'if they forget to submit data or if some other error occurs'
          ))

        # notice how you can access data returned from the context menu
        # of this node; using the label name in snake case
        print(node.cse_categories, node.query, node.pages) 

        ... # (removed code for clarity)

        if resp:
            for result in resp["results"]:
                url = result.get("breadcrumbUrl", {})
                # some elements you can store more than just a string,
                # (these elements storing dicts are mapped 
                # to janusgraph as properties with the names
                # result_title, result_subtitle, and result_text)
                blueprint = CSESearchResults.blueprint(
                    result={
                        "title": result.get("titleNoFormatting"),
                        "subtitle": url.get("host") + url.get("crumbs"),
                        "text": result.get("contentNoFormatting"),
                    },
                    url=result.get("unescapedUrl"),
                    cache_url=result.get("cacheUrl"),
                )
                results.append(blueprint)
        # here we return a list of blueprints (blueprints are dicts)
        # but you can also return a single blueprint without a list
        return results

```



