From fba6432f40eb9ed95a6d892a796f93210c5064b5 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Wed, 15 May 2024 23:34:37 -0400 Subject: [PATCH 01/29] Switch to Poetry --- docs/README.md | 8 ++-- docs/pyproj/README.md | 26 +++++----- pyproject.toml | 58 +++++++++++++---------- sherlock/notify.py | 2 +- sherlock/sherlock.py | 8 ++-- sherlock/tests/base.py | 6 +-- sherlock/tests/test_multiple_usernames.py | 1 - 7 files changed, 56 insertions(+), 53 deletions(-) diff --git a/docs/README.md b/docs/README.md index fe3bcafc5..9f3c413c9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -27,11 +27,11 @@ [![PyPI - Version](https://img.shields.io/pypi/v/sherlock-project?logo=PyPi&label=PyPI&color=darkgreen)][ext_pypi] [![Docker Image Version](https://img.shields.io/docker/v/sherlock/sherlock?sort=semver&logo=docker&label=Docker&color=darkgreen)][docs_docker] [![homebrew version](https://img.shields.io/homebrew/v/sherlock?logo=Homebrew&color=darkgreen)][ext_brew] -| Method | Command | Notes | +| | Command | Notes | | - | - | - | -| pypi | `pipx install sherlock-project` | `pip` may be used in place of `pipx` | -| brew | `brew install sherlock` | Community supported | -| docker | `docker pull sherlock/sherlock` | | +| PyPI | `pipx install sherlock-project` | `pip` may be used in place of `pipx` | +| Homebrew | `brew install sherlock` | Community supported | +| Docker | `docker pull sherlock/sherlock` | | ### Alternative guides and methods diff --git a/docs/pyproj/README.md b/docs/pyproj/README.md index 446382f5f..f33358a55 100644 --- a/docs/pyproj/README.md +++ b/docs/pyproj/README.md @@ -2,17 +2,12 @@


- +
- Hunt down social media accounts by username across social networks + Hunt down social media accounts by username across 400+ social networks +

+ Additional documentation can be found at our GitHub repository
- Additional documentation can be found on our GitHub repository -
-

- -

- -

## Usage @@ -36,11 +31,12 @@ To search for more than one user: ```bash $ sherlock user1 user2 user3 ``` +
-## Star History +___ - - - - Sherlock Project Star History Chart - +
+

+ + +

diff --git a/pyproject.toml b/pyproject.toml index 7356c0d11..11228285e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,30 +1,26 @@ [build-system] -requires = ["setuptools >= 61.0"] -build-backend = "setuptools.build_meta" +requires = [ "poetry-core>=1.8.0", "poetry-dynamic-versioning>1.0.0,<2.0.0" ] +build-backend = "poetry_dynamic_versioning.backend" -[project.scripts] -sherlock = "sherlock:main" +[tool.poetry-dynamic-versioning] +enable = true +vcs = "git" -[project.urls] -Homepage = "http://sherlock-project.github.io/" -Repository = "https://github.com/sherlock-project/sherlock.git" -Issues = "https://github.com/sherlock-project/sherlock/issues" - -[project] +[tool.poetry] name = "sherlock-project" +version = "0.0.0" +description = "Hunt down social media accounts by username across social networks" +license = "MIT" authors = [ - { name = "Siddharth Dushantha" } + "Siddharth Dushantha" ] maintainers = [ - { name = "Matheus Felipe" }, - { name = "Sondre Karlsen Dyrnes" }, - { name = "Paul Pfeister" } + "Paul Pfeister", + "Matheus Felipe", + "Sondre Karlsen Dyrnes" ] -description = "Hunt down social media accounts by username across social networks" readme = "docs/pyproj/README.md" -# Do not set license to file. Causes issues with rpm packaging for some reason. -license = {text = "MIT"} -dynamic = ["dependencies", "version"] +packages = [ { include = "sherlock" } ] keywords = [ "osint", "reconnaissance", "information gathering" ] classifiers = [ "Development Status :: 5 - Production/Stable", @@ -37,12 +33,24 @@ classifiers = [ "Topic :: Security" ] -[tool.setuptools.dynamic] -dependencies = { file = [ "requirements.txt" ] } -version = { attr = "sherlock.__version__" } -[tool.setuptools] -package-dir = {"" = "sherlock"} +[tool.poetry.urls] +Homepage = "http://sherlock-project.github.io/" +Repository = "https://github.com/sherlock-project/sherlock.git" +Issues = "https://github.com/sherlock-project/sherlock/issues" + +[tool.poetry.dependencies] +python = "^3.8" +certifi = "^2019.6.16" +colorama = "^0.4.1" +PySocks = "^1.7.0" +requests = "^2.22.0" +requests-futures = "^1.0.0" +stem = "^1.8.0" +torrequest = "^0.1.0" +pandas = ">1.0.0" +openpyxl = "^3.0.10" +exrex = "^0.11.0" -[tool.setuptools.package-data] -"*" = ["*.json"] +[tool.poetry.scripts] +sherlock = 'sherlock.sherlock:main' diff --git a/sherlock/notify.py b/sherlock/notify.py index 4af1ff18e..c198fe620 100644 --- a/sherlock/notify.py +++ b/sherlock/notify.py @@ -3,7 +3,7 @@ This module defines the objects for notifying the caller about the results of queries. """ -from result import QueryStatus +from sherlock.result import QueryStatus from colorama import Fore, Style import webbrowser diff --git a/sherlock/sherlock.py b/sherlock/sherlock.py index 3f7a93391..d48791942 100644 --- a/sherlock/sherlock.py +++ b/sherlock/sherlock.py @@ -21,10 +21,10 @@ from requests_futures.sessions import FuturesSession from torrequest import TorRequest -from result import QueryStatus -from result import QueryResult -from notify import QueryNotifyPrint -from sites import SitesInformation +from sherlock.result import QueryStatus +from sherlock.result import QueryResult +from sherlock.notify import QueryNotifyPrint +from sherlock.sites import SitesInformation from colorama import init from argparse import ArgumentTypeError diff --git a/sherlock/tests/base.py b/sherlock/tests/base.py index de958b9db..204c19c0a 100644 --- a/sherlock/tests/base.py +++ b/sherlock/tests/base.py @@ -6,9 +6,9 @@ import os.path import unittest import sherlock -from result import QueryStatus -from notify import QueryNotify -from sites import SitesInformation +from sherlock.result import QueryStatus +from sherlock.notify import QueryNotify +from sherlock.sites import SitesInformation import warnings diff --git a/sherlock/tests/test_multiple_usernames.py b/sherlock/tests/test_multiple_usernames.py index 418110877..3be803330 100644 --- a/sherlock/tests/test_multiple_usernames.py +++ b/sherlock/tests/test_multiple_usernames.py @@ -1,4 +1,3 @@ -import importlib import unittest import sys sys.path.append('../') From de8ebb1577035bfbf44c7a4b3df537d98abba077 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Wed, 15 May 2024 23:53:37 -0400 Subject: [PATCH 02/29] Relocate unit tests --- docs/CONTRIBUTING.md | 2 +- {sherlock/tests => tests}/__init__.py | 0 {sherlock/tests => tests}/all.py | 0 {sherlock/tests => tests}/base.py | 4 ++-- {sherlock/tests => tests}/test_multiple_usernames.py | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename {sherlock/tests => tests}/__init__.py (100%) rename {sherlock/tests => tests}/all.py (100%) rename {sherlock/tests => tests}/base.py (98%) rename {sherlock/tests => tests}/test_multiple_usernames.py (90%) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 4f1ff4c32..2d3d6733d 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -68,7 +68,7 @@ Sherlock. This invocation hides the progress text that Sherlock normally outputs, and instead shows the verbose output of the tests. ```console -$ cd sherlock/sherlock +# Assumes pwd is respository root $ python3 -m unittest tests.all --verbose ``` diff --git a/sherlock/tests/__init__.py b/tests/__init__.py similarity index 100% rename from sherlock/tests/__init__.py rename to tests/__init__.py diff --git a/sherlock/tests/all.py b/tests/all.py similarity index 100% rename from sherlock/tests/all.py rename to tests/all.py diff --git a/sherlock/tests/base.py b/tests/base.py similarity index 98% rename from sherlock/tests/base.py rename to tests/base.py index 204c19c0a..2146b88b2 100644 --- a/sherlock/tests/base.py +++ b/tests/base.py @@ -5,7 +5,7 @@ import os import os.path import unittest -import sherlock +from sherlock import sherlock from sherlock.result import QueryStatus from sherlock.notify import QueryNotify from sherlock.sites import SitesInformation @@ -30,7 +30,7 @@ def setUp(self): warnings.simplefilter("ignore", ResourceWarning) # Create object with all information about sites we are aware of. - sites = SitesInformation(data_file_path=os.path.join(os.path.dirname(__file__), "../resources/data.json")) + sites = SitesInformation(data_file_path=os.path.join(os.path.dirname(__file__), "../sherlock/resources/data.json")) # Create original dictionary from SitesInformation() object. # Eventually, the rest of the code will be updated to use the new object diff --git a/sherlock/tests/test_multiple_usernames.py b/tests/test_multiple_usernames.py similarity index 90% rename from sherlock/tests/test_multiple_usernames.py rename to tests/test_multiple_usernames.py index 3be803330..3e8a307ee 100644 --- a/sherlock/tests/test_multiple_usernames.py +++ b/tests/test_multiple_usernames.py @@ -1,7 +1,7 @@ import unittest import sys sys.path.append('../') -import sherlock as sh +from sherlock import sherlock as sh checksymbols = [] checksymbols = ["_", "-", "."] From b2a69b519895a2acc6926164e3e9b707c184dd22 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 00:06:49 -0400 Subject: [PATCH 03/29] Remove setup.[cfg|py] --- setup.cfg | 4 ---- setup.py | 8 -------- 2 files changed, 12 deletions(-) delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 8929bbae7..000000000 --- a/setup.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[metadata] -name = Sherlock -author = Sherlock Project -url = http://sherlock-project.github.io/ diff --git a/setup.py b/setup.py deleted file mode 100644 index 434d3f95e..000000000 --- a/setup.py +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python3 - -"""Sometimes required for rpm spec - particularly when using pyp2rpm -""" - -from setuptools import setup - -setup() From caed51e268132c4e495ef25d1d09039d93eb2c1f Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 00:08:00 -0400 Subject: [PATCH 04/29] Remove rpm spec --- .github/CODEOWNERS | 1 - sherlock-project.spec | 71 ------------------------------------------- 2 files changed, 72 deletions(-) delete mode 100644 sherlock-project.spec diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 76001ae9a..e2a358d90 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,4 +8,3 @@ /pyproject.toml @ppfeister @sdushantha /setup.cfg @ppfeister @sdushantha /setup.py @ppfeister -/*.spec @ppfeister diff --git a/sherlock-project.spec b/sherlock-project.spec deleted file mode 100644 index b07dded1a..000000000 --- a/sherlock-project.spec +++ /dev/null @@ -1,71 +0,0 @@ -# Packager: Paul Pfeister (GitHub @ppfeister) -%global source_ref master - -Name: sherlock-project -Version: 0.14.4 -Release: %autorelease -Summary: Hunt down social media accounts by username across social networks - -License: MIT -URL: https://github.com/sherlock-project/sherlock -Source: %{url}/archive/%{source_ref}.tar.gz -# Switch to new Source URL after adoption of tagged releases - -BuildArch: noarch -BuildRequires: python3-devel -BuildRequires: help2man - -%global _description %{expand: -Hunt down social media accounts by username across 400+ social networks and -websites. New targets are tested and implemented regularly. -} - -%description %{_description} - - -%prep -%autosetup -n sherlock-%{source_ref} - - -%generate_buildrequires -%pyproject_buildrequires - - -%build -%pyproject_wheel - - -%install -%pyproject_install -%pyproject_save_files -l sherlock sites result notify __init__ __main__ - -sed -r -i '1{/^#!/d}' '%{buildroot}%{python3_sitelib}/__main__.py' -sed -r -i '1{/^#!/d}' '%{buildroot}%{python3_sitelib}/sherlock.py' - -install -d '%{buildroot}%{_mandir}/man1' -PYTHONPATH='%{buildroot}%{python3_sitelib}' help2man \ - --no-info \ - --version-string='%{version}' \ - --name='%{summary}' \ - --output='%{buildroot}%{_mandir}/man1/sherlock.1' \ - '%{buildroot}%{_bindir}/sherlock' - - -%check -# Tests fail when pwd isn't sherlock. Relative pathing need fix upstream. -cd sherlock -%{py3_test_envvars} %{python3} -m unittest tests.all --verbose -cd .. - - -%files -f %{pyproject_files} -%doc README.md -%{_bindir}/sherlock -%{python3_sitelib}/resources -%pycached %{python3_sitelib}/tests/*.py -%{_mandir}/man1/sherlock.1* - - -%changelog -* Tue May 14 2024 Paul Pfeister 0.14.4-1 -- Initial package. From 44bc8523dd89e8ae38179361526730463558a9c3 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 00:08:40 -0400 Subject: [PATCH 05/29] Remove setup.[cfg|py] from codeowners --- .github/CODEOWNERS | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e2a358d90..ae6c8b316 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,5 +6,3 @@ # Changes made to these items without code owner approval may negatively # impact packaging pipelines. Code owners may need time to verify or adapt. /pyproject.toml @ppfeister @sdushantha -/setup.cfg @ppfeister @sdushantha -/setup.py @ppfeister From 9f58f93562a066c04d5f110f0cde57b0a22a735e Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 00:09:23 -0400 Subject: [PATCH 06/29] Remove requirements.txt --- requirements.txt | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index b1dd62522..000000000 --- a/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -certifi>=2019.6.16 -colorama>=0.4.1 -PySocks>=1.7.0 -requests>=2.22.0 -requests-futures>=1.0.0 -stem>=1.8.0 -torrequest>=0.1.0 -pandas>=1.0.0 -openpyxl>=3.0.10 -exrex>=0.11.0 From 6b0995599ac56ed30fe5d228b9b8230965f92dae Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 00:16:46 -0400 Subject: [PATCH 07/29] Remove install redirect --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 11228285e..0aaf259e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ maintainers = [ "Sondre Karlsen Dyrnes" ] readme = "docs/pyproj/README.md" -packages = [ { include = "sherlock" } ] +packages = [ { include = "sherlock"} ] keywords = [ "osint", "reconnaissance", "information gathering" ] classifiers = [ "Development Status :: 5 - Production/Stable", From 07227e4a9a87a4b08cce9722401d8539be7d4cce Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 02:09:41 -0400 Subject: [PATCH 08/29] Add dynamic versionin support (disabled) --- pyproject.toml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0aaf259e5..d17374902 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,12 +3,20 @@ requires = [ "poetry-core>=1.8.0", "poetry-dynamic-versioning>1.0.0,<2.0.0" ] build-backend = "poetry_dynamic_versioning.backend" [tool.poetry-dynamic-versioning] -enable = true +enable = false +metadata = false +strict = true vcs = "git" +# Matched tags: +# v0.0.0 followed by optional -rc0 (release candidate) OR -b0 (public beta) +pattern = "^v(?P\\d+(?:\\.\\d+){2})(?:-(?P(?:rc|b)\\d+?))??$" + +[tool.poetry-dynamic-versioning.substitution] +folders = [ { path = "sherlock" } ] [tool.poetry] name = "sherlock-project" -version = "0.0.0" +version = "0.14.4" description = "Hunt down social media accounts by username across social networks" license = "MIT" authors = [ @@ -32,12 +40,13 @@ classifiers = [ "Programming Language :: Python :: 3", "Topic :: Security" ] +homepage = "http://sherlock-project.github.io/" +repository = "https://github.com/sherlock-project/sherlock.git" [tool.poetry.urls] -Homepage = "http://sherlock-project.github.io/" -Repository = "https://github.com/sherlock-project/sherlock.git" -Issues = "https://github.com/sherlock-project/sherlock/issues" +"Bug Reporting" = "https://github.com/sherlock-project/sherlock/issues" +"Contributors" = "https://github.com/sherlock-project/sherlock/graphs/contributors" [tool.poetry.dependencies] python = "^3.8" From af7565ec3d830057773279f12a9abb6521e370da Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 02:51:06 -0400 Subject: [PATCH 09/29] Allow higher certifi --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d17374902..1176963bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ repository = "https://github.com/sherlock-project/sherlock.git" [tool.poetry.dependencies] python = "^3.8" -certifi = "^2019.6.16" +certifi = ">2019.6.16" colorama = "^0.4.1" PySocks = "^1.7.0" requests = "^2.22.0" From 36c274ec19c9c7e6ce1bdcb888898e54649cce9f Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 03:07:31 -0400 Subject: [PATCH 10/29] Remove License classifier --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1176963bd..858681b39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,6 @@ classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Intended Audience :: Information Technology", - "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3", From e58057820fc486d28c626f1ee5e49ece0d7e5e36 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 04:00:05 -0400 Subject: [PATCH 11/29] Downgrade poetry-core --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 858681b39..2f5cfd19c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,7 @@ [build-system] -requires = [ "poetry-core>=1.8.0", "poetry-dynamic-versioning>1.0.0,<2.0.0" ] +requires = [ "poetry-core>=1.6.0", "poetry-dynamic-versioning>1.0.0,<2.0.0" ] build-backend = "poetry_dynamic_versioning.backend" +# poetry-core 1.8 not available in .fc39. Can upgrade to 1.8.0 at .fc39 EOL [tool.poetry-dynamic-versioning] enable = false From 3b713ed0084c5dea7ce985e4bf2a2de77c3c4be3 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 23:36:55 -0400 Subject: [PATCH 12/29] Fix cli mod exec import --- sherlock/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sherlock/__main__.py b/sherlock/__main__.py index b10bd6aef..39068a06a 100644 --- a/sherlock/__main__.py +++ b/sherlock/__main__.py @@ -18,5 +18,5 @@ print(f"Sherlock requires Python 3.6+\nYou are using Python {python_version}, which is not supported by Sherlock.") sys.exit(1) - import sherlock + from sherlock import sherlock sherlock.main() From 63a1c1448a19643386ee71867f135978df4f97d4 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 23:37:03 -0400 Subject: [PATCH 13/29] Fix version string --- sherlock/sherlock.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sherlock/sherlock.py b/sherlock/sherlock.py index d48791942..e3474d1db 100644 --- a/sherlock/sherlock.py +++ b/sherlock/sherlock.py @@ -510,9 +510,9 @@ def handler(signal_received, frame): def main(): version_string = ( - f"%(prog)s {__version__}\n" - + f"{requests.__description__}: {requests.__version__}\n" - + f"Python: {platform.python_version()}" + f"Sherlock {__version__}\n" + + f"Requests {requests.__version__}\n" + + f"Python {platform.python_version()}" ) parser = ArgumentParser( From ea1c4218382985f5148388d2d27609412c976389 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Thu, 16 May 2024 23:47:10 -0400 Subject: [PATCH 14/29] Update docs with module changes --- docs/README.md | 5 ----- docs/install.md | 19 ++++++++++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/README.md b/docs/README.md index 9f3c413c9..5835de446 100644 --- a/docs/README.md +++ b/docs/README.md @@ -133,15 +133,10 @@ Original Creator - [Siddharth Dushantha](https://github.com/sdushantha) [docs_install]: /docs/install.md [docs_docker]: /docs/install.md#docker -[docs_docker_dockerhub]: /docs/install.md#docker -[docs_docker_compose]: /docs/install.md#using-compose -[docs_docker_source]: /docs/install.md#build-image-from-source-useful-for-contributors [docs_py]: /docs/install.md#python -[docs_py_build]: /docs/install.md#build-python-package-from-source-useful-for-contributors [docs_contrib]: /docs/CONTRIBUTING.md [docs_contrib_adding_targets]: /docs/CONTRIBUTING.md#adding-targets [docs_contrib_removing_targets]: /docs/CONTRIBUTING.md#removing-targets [docs_contrib_restoring_targets]: /docs/CONTRIBUTING.md#restoring-targets [ext_pypi]: https://pypi.org/project/sherlock-project/ [ext_brew]: https://formulae.brew.sh/formula/sherlock - diff --git a/docs/install.md b/docs/install.md index 9813a09c0..0a5069d92 100644 --- a/docs/install.md +++ b/docs/install.md @@ -37,13 +37,22 @@ Python pipx install sherlock-project ``` -### Build python package from source (useful for contributors) +### Build live package from source (useful for contributors) + +Building an editable (or live) package links the entry point to your current directory, rather than to the standard install location. This is often useful when working with the code base, as changes are reflected immediately without reinstallation. ```bash -# pipx is recommended, but pip may suffice if pipx is unavailable -git clone https://github.com/sherlock-project/sherlock.git -cd sherlock -pipx install . +# Assumes repository cloned, and pwd is repository root +pipx install -e . +``` + +### Run package from source (no install) + +If you'd rather not install directly to your system, you can import the module at runtime with `-m`. + +```bash +# Assumes repository cloned, and pwd is repository root +python3 -m sherlock user123 user789 ```

From 7867e26868e87c8a6f4feee23104a05f8cac82cf Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Fri, 17 May 2024 00:19:08 -0400 Subject: [PATCH 15/29] Remove upper limit --- pyproject.toml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2f5cfd19c..f3a8d74ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,16 +50,16 @@ repository = "https://github.com/sherlock-project/sherlock.git" [tool.poetry.dependencies] python = "^3.8" -certifi = ">2019.6.16" -colorama = "^0.4.1" -PySocks = "^1.7.0" -requests = "^2.22.0" -requests-futures = "^1.0.0" -stem = "^1.8.0" -torrequest = "^0.1.0" -pandas = ">1.0.0" -openpyxl = "^3.0.10" -exrex = "^0.11.0" +certifi = ">=2019.6.16" +colorama = ">=0.4.1" +PySocks = ">=1.7.0" +requests = ">=2.22.0" +requests-futures = ">=1.0.0" +stem = ">=1.8.0" +torrequest = ">=0.1.0" +pandas = ">=1.0.0" +openpyxl = ">=3.0.10" +exrex = ">=0.11.0" [tool.poetry.scripts] sherlock = 'sherlock.sherlock:main' From 8fee9a971437eb55334fb720380f0b5b01e00e24 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Fri, 17 May 2024 20:02:14 -0400 Subject: [PATCH 16/29] Ignore Poetry --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4d47421ae..c91732b47 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,9 @@ -# Virtual Environment +# Virtual Environments venv/ bin/ lib/ pyvenv.cfg +poetry.lock # Editor Configurations .vscode/ From b485001fcb7b99c6eb76334693c4a32d54d78f89 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Fri, 17 May 2024 20:57:37 -0400 Subject: [PATCH 17/29] Switch versioning plugin --- pyproject.toml | 19 +++++-------------- sherlock/__init__.py | 4 ++++ sherlock/__main__.py | 4 ++-- sherlock/sherlock.py | 20 ++++++++++++++------ 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f3a8d74ba..04844acee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,23 +1,14 @@ [build-system] -requires = [ "poetry-core>=1.6.0", "poetry-dynamic-versioning>1.0.0,<2.0.0" ] -build-backend = "poetry_dynamic_versioning.backend" +requires = [ "poetry-core>=1.2.0" ] +build-backend = "poetry.core.masonry.api" # poetry-core 1.8 not available in .fc39. Can upgrade to 1.8.0 at .fc39 EOL -[tool.poetry-dynamic-versioning] -enable = false -metadata = false -strict = true -vcs = "git" -# Matched tags: -# v0.0.0 followed by optional -rc0 (release candidate) OR -b0 (public beta) -pattern = "^v(?P\\d+(?:\\.\\d+){2})(?:-(?P(?:rc|b)\\d+?))??$" - -[tool.poetry-dynamic-versioning.substitution] -folders = [ { path = "sherlock" } ] +[tool.poetry-version-plugin] +source = "init" [tool.poetry] name = "sherlock-project" -version = "0.14.4" +version = "0" # single source of truth is __version__.py description = "Hunt down social media accounts by username across social networks" license = "MIT" authors = [ diff --git a/sherlock/__init__.py b/sherlock/__init__.py index 219dcaec7..5bf79e243 100644 --- a/sherlock/__init__.py +++ b/sherlock/__init__.py @@ -4,3 +4,7 @@ networks. """ + +__shortname__ = "Sherlock" +__longname__ = "Sherlock: Find Usernames Across Social Networks" +__version__ = "0.14.4" diff --git a/sherlock/__main__.py b/sherlock/__main__.py index 39068a06a..014d8b353 100644 --- a/sherlock/__main__.py +++ b/sherlock/__main__.py @@ -14,8 +14,8 @@ # Check if the user is using the correct version of Python python_version = sys.version.split()[0] - if sys.version_info < (3, 6): - print(f"Sherlock requires Python 3.6+\nYou are using Python {python_version}, which is not supported by Sherlock.") + if sys.version_info < (3, 8): + print(f"Sherlock requires Python 3.8+\nYou are using Python {python_version}, which is not supported by Sherlock.") sys.exit(1) from sherlock import sherlock diff --git a/sherlock/sherlock.py b/sherlock/sherlock.py index e3474d1db..9846cb5a5 100644 --- a/sherlock/sherlock.py +++ b/sherlock/sherlock.py @@ -19,6 +19,17 @@ import requests +# Removing __version__ here will trigger update message for users +# Do not remove until ready to trigger that message +__version__ = "0.14.4" +del __version__ + +from .__init__ import ( + __shortname__, + __longname__, + __version__ +) + from requests_futures.sessions import FuturesSession from torrequest import TorRequest from sherlock.result import QueryStatus @@ -28,9 +39,6 @@ from colorama import init from argparse import ArgumentTypeError -module_name = "Sherlock: Find Usernames Across Social Networks" -__version__ = "0.14.4" - class SherlockFuturesSession(FuturesSession): def request(self, method, url, hooks=None, *args, **kwargs): @@ -510,14 +518,14 @@ def handler(signal_received, frame): def main(): version_string = ( - f"Sherlock {__version__}\n" + f"{__shortname__} {__version__}\n" + f"Requests {requests.__version__}\n" - + f"Python {platform.python_version()}" + + f"Python {platform.python_version()}" ) parser = ArgumentParser( formatter_class=RawDescriptionHelpFormatter, - description=f"{module_name} (Version {__version__})", + description=f"{__longname__} (Version {__version__})", ) parser.add_argument( "--version", From 41f798a34e3e807d6a8d7b00cd6469b24bd4e442 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Fri, 17 May 2024 21:29:52 -0400 Subject: [PATCH 18/29] Ignore dist --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c91732b47..c53e34ad9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,8 +15,9 @@ __pycache__/ # Pip src/ -# Pip / PyProject Devel & Installation +# Devel, Build, and Installation *.egg-info/ +dist/** # Jupyter Notebook .ipynb_checkpoints From 33bbb4e720a92e496fcf46f900476c75f2339123 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Sat, 18 May 2024 00:35:24 -0400 Subject: [PATCH 19/29] Fix pyproject URLs Co-authored-by: Matheus Felipe --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 04844acee..3b396b315 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,8 +31,8 @@ classifiers = [ "Programming Language :: Python :: 3", "Topic :: Security" ] -homepage = "http://sherlock-project.github.io/" -repository = "https://github.com/sherlock-project/sherlock.git" +homepage = "https://sherlock-project.github.io/" +repository = "https://github.com/sherlock-project/sherlock" [tool.poetry.urls] From 16e6ee639b1cdc9e5b045724d5b8140ac92e36e4 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Sat, 18 May 2024 01:01:37 -0400 Subject: [PATCH 20/29] Add email to maintainers Co-authored-by: Matheus Felipe --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3b396b315..db760506c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,9 +15,9 @@ authors = [ "Siddharth Dushantha" ] maintainers = [ - "Paul Pfeister", - "Matheus Felipe", - "Sondre Karlsen Dyrnes" + "Paul Pfeister ", + "Matheus Felipe ", + "Sondre Karlsen Dyrnes " ] readme = "docs/pyproj/README.md" packages = [ { include = "sherlock"} ] From 606743b99d7d8b42b40eefdfea4d2d233d305bb9 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Sat, 18 May 2024 01:29:11 -0400 Subject: [PATCH 21/29] Remove tor --- sherlock/sherlock.py | 58 +++----------------------------------------- tests/base.py | 4 --- 2 files changed, 4 insertions(+), 58 deletions(-) diff --git a/sherlock/sherlock.py b/sherlock/sherlock.py index 9846cb5a5..7d894246c 100644 --- a/sherlock/sherlock.py +++ b/sherlock/sherlock.py @@ -31,7 +31,6 @@ ) from requests_futures.sessions import FuturesSession -from torrequest import TorRequest from sherlock.result import QueryStatus from sherlock.result import QueryResult from sherlock.notify import QueryNotifyPrint @@ -167,8 +166,6 @@ def sherlock( username, site_data, query_notify, - tor=False, - unique_tor=False, proxy=None, timeout=60, ): @@ -183,8 +180,6 @@ def sherlock( query_notify -- Object with base type of QueryNotify(). This will be used to notify the caller about query results. - tor -- Boolean indicating whether to use a tor circuit for the requests. - unique_tor -- Boolean indicating whether to use a new tor circuit for each request. proxy -- String indicating the proxy URL timeout -- Time in seconds to wait before timing out request. Default is 60 seconds. @@ -205,20 +200,10 @@ def sherlock( # Notify caller that we are starting the query. query_notify.start(username) - # Create session based on request methodology - if tor or unique_tor: - # Requests using Tor obfuscation - try: - underlying_request = TorRequest() - except OSError: - print("Tor not found in system path. Unable to continue.\n") - sys.exit(query_notify.finish()) - underlying_session = underlying_request.session - else: - # Normal requests - underlying_session = requests.session() - underlying_request = requests.Request() + # Normal requests + underlying_session = requests.session() + underlying_request = requests.Request() # Limit number of workers to 20. # This is probably vastly overkill. @@ -342,15 +327,10 @@ def sherlock( # Store future in data for access later net_info["request_future"] = future - # Reset identify for tor (if needed) - if unique_tor: - underlying_request.reset_identity() - # Add this site's results into final dictionary with all the other results. results_total[social_network] = results_site # Open the file containing account links - # Core logic: If tor requests, make them here. If multi-threaded requests, wait for responses for social_network, net_info in site_data.items(): # Retrieve results again results_site = results_total.get(social_network) @@ -554,23 +534,7 @@ def main(): "-o", dest="output", help="If using single username, the output of the result will be saved to this file.", - ) - parser.add_argument( - "--tor", - "-t", - action="store_true", - dest="tor", - default=False, - help="Make requests over Tor; increases runtime; requires Tor to be installed and in system path.", - ) - parser.add_argument( - "--unique-tor", - "-u", - action="store_true", - dest="unique_tor", - default=False, - help="Make requests over Tor with new Tor circuit after each request; increases runtime; requires Tor to be installed and in system path.", - ) + ), parser.add_argument( "--csv", action="store_true", @@ -694,22 +658,10 @@ def main(): except Exception as error: print(f"A problem occurred while checking for an update: {error}") - # Argument check - # TODO regex check on args.proxy - if args.tor and (args.proxy is not None): - raise Exception("Tor and Proxy cannot be set at the same time.") - # Make prompts if args.proxy is not None: print("Using the proxy: " + args.proxy) - if args.tor or args.unique_tor: - print("Using Tor to make requests") - - print( - "Warning: some websites might refuse connecting over Tor, so note that using this option might increase connection errors." - ) - if args.no_color: # Disable color output. init(strip=True, convert=False) @@ -788,8 +740,6 @@ def main(): username, site_data, query_notify, - tor=args.tor, - unique_tor=args.unique_tor, proxy=args.proxy, timeout=args.timeout, ) diff --git a/tests/base.py b/tests/base.py index 2146b88b2..bda809948 100644 --- a/tests/base.py +++ b/tests/base.py @@ -51,8 +51,6 @@ def setUp(self): # Create notify object for query results. self.query_notify = QueryNotify() - self.tor = False - self.unique_tor = False self.timeout = None self.skip_error_sites = True @@ -115,8 +113,6 @@ def username_check(self, username_list, site_list, exist_check=True): results = sherlock.sherlock(username, site_data, self.query_notify, - tor=self.tor, - unique_tor=self.unique_tor, timeout=self.timeout ) for site, result in results.items(): From 4b7fd8b59dd134f116f81544a4f7b01f149bf1a9 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Sat, 18 May 2024 02:22:18 -0400 Subject: [PATCH 22/29] Fix typos --- pyproject.toml | 3 ++- sherlock/sherlock.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index db760506c..6c0eb1940 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,8 @@ source = "init" [tool.poetry] name = "sherlock-project" -version = "0" # single source of truth is __version__.py +# single source of truth for version is __init__.py +version = "0" description = "Hunt down social media accounts by username across social networks" license = "MIT" authors = [ diff --git a/sherlock/sherlock.py b/sherlock/sherlock.py index 7d894246c..88fab987a 100644 --- a/sherlock/sherlock.py +++ b/sherlock/sherlock.py @@ -534,7 +534,7 @@ def main(): "-o", dest="output", help="If using single username, the output of the result will be saved to this file.", - ), + ) parser.add_argument( "--csv", action="store_true", From ba2eef7b0e650335841c2140ae794354a8d65198 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Sat, 18 May 2024 02:41:25 -0400 Subject: [PATCH 23/29] Revert "Remove tor" This reverts commit 606743b99d7d8b42b40eefdfea4d2d233d305bb9. --- sherlock/sherlock.py | 56 +++++++++++++++++++++++++++++++++++++++++--- tests/base.py | 4 ++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/sherlock/sherlock.py b/sherlock/sherlock.py index 88fab987a..9846cb5a5 100644 --- a/sherlock/sherlock.py +++ b/sherlock/sherlock.py @@ -31,6 +31,7 @@ ) from requests_futures.sessions import FuturesSession +from torrequest import TorRequest from sherlock.result import QueryStatus from sherlock.result import QueryResult from sherlock.notify import QueryNotifyPrint @@ -166,6 +167,8 @@ def sherlock( username, site_data, query_notify, + tor=False, + unique_tor=False, proxy=None, timeout=60, ): @@ -180,6 +183,8 @@ def sherlock( query_notify -- Object with base type of QueryNotify(). This will be used to notify the caller about query results. + tor -- Boolean indicating whether to use a tor circuit for the requests. + unique_tor -- Boolean indicating whether to use a new tor circuit for each request. proxy -- String indicating the proxy URL timeout -- Time in seconds to wait before timing out request. Default is 60 seconds. @@ -200,10 +205,20 @@ def sherlock( # Notify caller that we are starting the query. query_notify.start(username) + # Create session based on request methodology + if tor or unique_tor: + # Requests using Tor obfuscation + try: + underlying_request = TorRequest() + except OSError: + print("Tor not found in system path. Unable to continue.\n") + sys.exit(query_notify.finish()) - # Normal requests - underlying_session = requests.session() - underlying_request = requests.Request() + underlying_session = underlying_request.session + else: + # Normal requests + underlying_session = requests.session() + underlying_request = requests.Request() # Limit number of workers to 20. # This is probably vastly overkill. @@ -327,10 +342,15 @@ def sherlock( # Store future in data for access later net_info["request_future"] = future + # Reset identify for tor (if needed) + if unique_tor: + underlying_request.reset_identity() + # Add this site's results into final dictionary with all the other results. results_total[social_network] = results_site # Open the file containing account links + # Core logic: If tor requests, make them here. If multi-threaded requests, wait for responses for social_network, net_info in site_data.items(): # Retrieve results again results_site = results_total.get(social_network) @@ -535,6 +555,22 @@ def main(): dest="output", help="If using single username, the output of the result will be saved to this file.", ) + parser.add_argument( + "--tor", + "-t", + action="store_true", + dest="tor", + default=False, + help="Make requests over Tor; increases runtime; requires Tor to be installed and in system path.", + ) + parser.add_argument( + "--unique-tor", + "-u", + action="store_true", + dest="unique_tor", + default=False, + help="Make requests over Tor with new Tor circuit after each request; increases runtime; requires Tor to be installed and in system path.", + ) parser.add_argument( "--csv", action="store_true", @@ -658,10 +694,22 @@ def main(): except Exception as error: print(f"A problem occurred while checking for an update: {error}") + # Argument check + # TODO regex check on args.proxy + if args.tor and (args.proxy is not None): + raise Exception("Tor and Proxy cannot be set at the same time.") + # Make prompts if args.proxy is not None: print("Using the proxy: " + args.proxy) + if args.tor or args.unique_tor: + print("Using Tor to make requests") + + print( + "Warning: some websites might refuse connecting over Tor, so note that using this option might increase connection errors." + ) + if args.no_color: # Disable color output. init(strip=True, convert=False) @@ -740,6 +788,8 @@ def main(): username, site_data, query_notify, + tor=args.tor, + unique_tor=args.unique_tor, proxy=args.proxy, timeout=args.timeout, ) diff --git a/tests/base.py b/tests/base.py index bda809948..2146b88b2 100644 --- a/tests/base.py +++ b/tests/base.py @@ -51,6 +51,8 @@ def setUp(self): # Create notify object for query results. self.query_notify = QueryNotify() + self.tor = False + self.unique_tor = False self.timeout = None self.skip_error_sites = True @@ -113,6 +115,8 @@ def username_check(self, username_list, site_list, exist_check=True): results = sherlock.sherlock(username, site_data, self.query_notify, + tor=self.tor, + unique_tor=self.unique_tor, timeout=self.timeout ) for site, result in results.items(): From 377e0766a251d55aa2f33a70729146e3eb69daee Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Sat, 18 May 2024 14:29:33 -0400 Subject: [PATCH 24/29] Update pyproject.toml Co-authored-by: Matheus Felipe --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6c0eb1940..8bb9f3d2c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ version = "0" description = "Hunt down social media accounts by username across social networks" license = "MIT" authors = [ - "Siddharth Dushantha" + "Siddharth Dushantha " ] maintainers = [ "Paul Pfeister ", From 313d2a9080703366d6cd763c5e25b12c360e4609 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Sat, 18 May 2024 17:28:50 -0400 Subject: [PATCH 25/29] Caret depends --- pyproject.toml | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8bb9f3d2c..5439fd959 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,21 +37,20 @@ repository = "https://github.com/sherlock-project/sherlock" [tool.poetry.urls] -"Bug Reporting" = "https://github.com/sherlock-project/sherlock/issues" -"Contributors" = "https://github.com/sherlock-project/sherlock/graphs/contributors" +"Bug Tracker" = "https://github.com/sherlock-project/sherlock/issues" [tool.poetry.dependencies] python = "^3.8" certifi = ">=2019.6.16" -colorama = ">=0.4.1" -PySocks = ">=1.7.0" -requests = ">=2.22.0" -requests-futures = ">=1.0.0" -stem = ">=1.8.0" -torrequest = ">=0.1.0" -pandas = ">=1.0.0" -openpyxl = ">=3.0.10" -exrex = ">=0.11.0" +colorama = "^0.4.1" +PySocks = "^1.7.0" +requests = "^2.22.0" +requests-futures = "^1.0.0" +stem = "^1.8.0" +torrequest = "^0.1.0" +pandas = "^1.0.0" +openpyxl = "^3.0.10" +exrex = "^0.11.0" [tool.poetry.scripts] sherlock = 'sherlock.sherlock:main' From 1b0e50854f6a51bd50a5fb94b425a29dd40177df Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Sat, 18 May 2024 17:41:01 -0400 Subject: [PATCH 26/29] Allow pandas upgrade --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5439fd959..c91b92261 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,8 @@ requests = "^2.22.0" requests-futures = "^1.0.0" stem = "^1.8.0" torrequest = "^0.1.0" -pandas = "^1.0.0" +# pandas can likely be bumped up to ^2.0.0 after fc39 EOL +pandas = ">=1.0.0,<3.0.0" openpyxl = "^3.0.10" exrex = "^0.11.0" From 07274a9a2ce0067a4d6a78b014c9e907a1fe9842 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Sat, 18 May 2024 18:06:16 -0400 Subject: [PATCH 27/29] Add note about version number --- docs/install.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/install.md b/docs/install.md index 0a5069d92..52c70086e 100644 --- a/docs/install.md +++ b/docs/install.md @@ -41,6 +41,8 @@ pipx install sherlock-project Building an editable (or live) package links the entry point to your current directory, rather than to the standard install location. This is often useful when working with the code base, as changes are reflected immediately without reinstallation. +Note that the version number will be 0.0.0 for pipx local builds unless manually changed in the pyproject file (it will prompt the user for an update). + ```bash # Assumes repository cloned, and pwd is repository root pipx install -e . From 04ce7aa0bb841fe2a6675cf3766133d1d30559a0 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Mon, 20 May 2024 00:51:28 -0400 Subject: [PATCH 28/29] Change remote version URI --- sherlock/sherlock.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sherlock/sherlock.py b/sherlock/sherlock.py index 9846cb5a5..e029a59da 100644 --- a/sherlock/sherlock.py +++ b/sherlock/sherlock.py @@ -679,10 +679,10 @@ def main(): # Check for newer version of Sherlock. If it exists, let the user know about it try: r = requests.get( - "https://raw.githubusercontent.com/sherlock-project/sherlock/master/sherlock/sherlock.py" + "https://raw.githubusercontent.com/sherlock-project/sherlock/master/sherlock/__init__.py" ) - remote_version = str(re.findall('__version__ = "(.*)"', r.text)[0]) + remote_version = str(re.findall('__version__ *= *"(.*)"', r.text)[0]) local_version = __version__ if remote_version != local_version: From b8ca8aade48dd4b6497ef114e41067aac476da65 Mon Sep 17 00:00:00 2001 From: Paul Pfeister Date: Fri, 31 May 2024 14:42:28 -0400 Subject: [PATCH 29/29] Add Sponsor --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..b21b31ed8 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [ sdushantha, ppfeister ] \ No newline at end of file