├── .github └── workflows │ └── build.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── make_release.py ├── pyproject.toml ├── screenshot.png ├── setup.py ├── signal2html ├── __init__.py ├── __main__.py ├── __version__.py ├── addressbook.py ├── core.py ├── dbproto.py ├── exceptions.py ├── html.py ├── html_colors.py ├── linkify.py ├── models.py ├── templates │ └── thread.html ├── types.py ├── ui.py └── versioninfo.py └── tests ├── test_linkify.py └── test_versioninfo.py /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | python: 13 | name: Tests 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | matrix: 17 | # Can add others if deemed necessary 18 | os: [ 'ubuntu-latest' ] 19 | # minimal and latest 20 | py: [ '3.7', '3.11' ] 21 | 22 | steps: 23 | - name: Install Python ${{ matrix.py }} 24 | uses: actions/setup-python@v2 25 | with: 26 | python-version: ${{ matrix.py }} 27 | 28 | - name: Checkout 29 | uses: actions/checkout@v2 30 | 31 | - name: Run unit tests 32 | run: make test_direct 33 | 34 | - name: Run code quality tests (black) 35 | uses: psf/black@stable 36 | with: 37 | # keep in sync with .pre-commit-config.yaml 38 | version: "23.1.0" 39 | 40 | - name: Run code quality tests (isort) 41 | uses: jamescurtin/isort-action@master 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | */__pycache__ 2 | *.egg-info 3 | dist/ 4 | build/ 5 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/psf/black 3 | rev: 23.1.0 # keep in sync with Github Actions build.yml 4 | hooks: 5 | - id: black 6 | language_version: python3 7 | 8 | - repo: https://github.com/pycqa/isort 9 | rev: 5.12.0 10 | hooks: 11 | - id: isort 12 | name: isort (python) 13 | - id: isort 14 | name: isort (cython) 15 | types: [cython] 16 | - id: isort 17 | name: isort (pyi) 18 | types: [pyi] 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 0.2.11 4 | 5 | * Better checking for database availability 6 | 7 | ## Version 0.2.10 8 | 9 | * Bump version of dependency package [emoji](https://pypi.org/project/emoji) 10 | 11 | ## Version 0.2.9 12 | 13 | * Fix bug in [#59](https://github.com/GjjvdBurg/signal2html/issues/59). Thanks 14 | to aweinberg38 for reporting this issue and providing a patch. 15 | 16 | ## Version 0.2.8 17 | 18 | * Code fixes for group update messages (thanks to @prgarnett and @aweinberg38 19 | for reporting [#37](https://github.com/GjjvdBurg/signal2html/issues/57)) 20 | 21 | ## Version 0.2.7 22 | 23 | * Code fixes for missing message data 24 | 25 | ## Version 0.2.6 26 | 27 | * Bugfix for handling mentions 28 | 29 | ## Version 0.2.5 30 | 31 | * Add support for clickable urls (thanks to @sbaum for reporting 32 | [#37](https://github.com/GjjvdBurg/signal2html/issues/37)) 33 | * Display more message metadata (thanks to @ericthegrey in 34 | [#33](https://github.com/GjjvdBurg/signal2html/pull/33)) 35 | * Add header to threads as in the app (thanks to @Aztorius for suggesting this 36 | in [#39](https://github.com/GjjvdBurg/signal2html/issues/39)) 37 | * Minor formatting fixes for thread messages 38 | 39 | ## Version 0.2.4 40 | 41 | * Bugfix for resolving recipient names for database version 108 and higher 42 | (thanks to @sbaum for reporting 43 | [#34](https://github.com/GjjvdBurg/signal2html/issues/34)). 44 | 45 | ## Version 0.2.3 46 | 47 | * Bugfix for non-existent recipients (thanks to @ericthegrey 48 | [#30](https://github.com/GjjvdBurg/signal2html/issues/30)). 49 | * Expand color palette to match Signal (thanks to @ChemoCosmo for reporting 50 | this (see [#30](https://github.com/GjjvdBurg/signal2html/issues/30)). 51 | * Support messages for video calls and key change (thanks to @ericthegrey 52 | [#29](https://github.com/GjjvdBurg/signal2html/pull/29)). 53 | 54 | ## Version 0.2.2 55 | 56 | * Add support for mentions (thanks to @ericthegrey) 57 | * Fixes for output filenames and directories 58 | * Minor cleanup 59 | 60 | ## Version 0.2.1 61 | 62 | * Improve version tests (thanks to @ericthegrey) 63 | * Add support for reactions (thanks to @ericthegrey) 64 | 65 | ## Version 0.2.0 66 | 67 | * Clean up code using an Addressbook class for recipients (thanks to 68 | @ericthegrey [#15](https://github.com/GjjvdBurg/signal2html/pull/15)). 69 | 70 | ## Version 0.1.8 71 | 72 | * Add a fallback to download attachment of that are not image/audio/video, and 73 | add support for showing stickers 74 | ([#11](https://github.com/GjjvdBurg/signal2html/pull/11) thanks to 75 | @ericthegrey) 76 | 77 | ## Version 0.1.7 78 | 79 | * Add phone field for quote author (bugfix) 80 | 81 | ## Version 0.1.6 82 | 83 | * Use thread-specific filenames 84 | ([#10](https://github.com/GjjvdBurg/signal2html/pull/10) thanks to 85 | @ericthegrey) 86 | 87 | ## Version 0.1.5 88 | 89 | * Add dataclasses dependency for python 3.6 90 | 91 | ## Version 0.1.4 92 | 93 | * Replace absolute URLs for attachments with relative ones. 94 | 95 | ## Version 0.1.3 96 | 97 | * Fix fallback for recipient name (thanks to @Otto-AA!) 98 | * Add several mime-types to HTML template 99 | * Bugfix for recipient names and group detection 100 | ([issue #5](https://github.com/GjjvdBurg/signal2html/issues/5)) 101 | 102 | ## Version 0.1.2 103 | 104 | * Add support for more recent database versions 105 | * Move each thread to a separate folder in output directory 106 | * Copy attachments to the thread directory 107 | 108 | ## Version 0.1.1 109 | 110 | * Minor fixes (encoding, unknown quoted authors) 111 | 112 | ## Version 0.1.0 113 | 114 | * Initial release 115 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | gertjanvandenburg@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020-2021, signal2html contributors. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | recursive-include signal2html *.html 3 | exclude Makefile 4 | exclude .gitignore 5 | exclude make_release.py 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for easier installation and cleanup. 2 | # 3 | # Uses self-documenting macros from here: 4 | # http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html 5 | 6 | SHELL := bash 7 | .SHELLFLAGS := -eu -o pipefail -c 8 | MAKEFLAGS += --no-builtin-rules 9 | 10 | PACKAGE=signal2html 11 | DOC_DIR='./docs' 12 | VENV_DIR=/tmp/s2h_venv 13 | 14 | ################# 15 | # Makefile help # 16 | ################# 17 | 18 | .PHONY: help 19 | 20 | .DEFAULT_GOAL := help 21 | 22 | help: 23 | @grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) |\ 24 | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m\ 25 | %s\n", $$1, $$2}' 26 | 27 | ################ 28 | # Installation # 29 | ################ 30 | 31 | .PHONY: install 32 | 33 | install: ## Install for the current user using the default python command 34 | python setup.py install --user 35 | 36 | ################ 37 | # Distribution # 38 | ################ 39 | 40 | .PHONY: release dist 41 | 42 | release: ## Make a release 43 | python make_release.py 44 | 45 | dist: ## Make Python source distribution 46 | python setup.py sdist bdist_wheel 47 | 48 | ########### 49 | # Testing # 50 | ########### 51 | 52 | .PHONY: test 53 | 54 | test: venv ## Run unit tests in virtual environment 55 | source $(VENV_DIR)/bin/activate && green -a -s 1 -vv ./tests 56 | 57 | test_direct: ## Run unit tests without virtual environment (typically for CI) 58 | pip install .[tests] && python -m unittest discover -v ./tests 59 | 60 | cover: venv 61 | source $(VENV_DIR)/bin/activate && green -a -r -s 1 -vv ./tests 62 | 63 | ####################### 64 | # Virtual environment # 65 | ####################### 66 | 67 | .PHONY: venv 68 | 69 | venv: $(VENV_DIR)/bin/activate ## Create a virtual environment 70 | 71 | $(VENV_DIR)/bin/activate: 72 | test -d $(VENV_DIR) || python -m venv $(VENV_DIR) 73 | source $(VENV_DIR)/bin/activate && pip install -e .[dev] 74 | touch $(VENV_DIR)/bin/activate 75 | 76 | ############ 77 | # Clean up # 78 | ############ 79 | 80 | clean_venv: ## Clean up the virtual environment 81 | rm -rf $(VENV_DIR) 82 | 83 | clean: ## Clean build dist and egg directories left after install 84 | rm -rf ./dist 85 | rm -rf ./build 86 | rm -rf ./$(PACKAGE).egg-info 87 | rm -rf ./cover 88 | rm -rf $(VENV_DIR) 89 | rm -f MANIFEST 90 | rm -f ./*_valgrind.log* 91 | find . -type f -iname '*.pyc' -delete 92 | find . -type d -name '__pycache__' -empty -delete 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # signal2html: Convert Signal backups to pretty HTML 2 | 3 | [](https://github.com/GjjvdBurg/signal2html/actions/workflows/build.yml) 4 | [](https://pypi.org/project/signal2html) 5 | [](https://pepy.tech/project/signal2html) 6 | 7 | This is a Python script to convert a backup of [Signal](https://signal.org/) 8 | messages to pretty HTML: 9 | 10 |
11 |
12 |