diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c1e09b9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+pyenv
+__pycache__/
+.ruff_cache
+.vscode
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..6a1f558
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,4 @@
+# Changelog
+
+## 0.1.0 (unreleased)
+- Initial release
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..ed3f7f7
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,134 @@
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall
+ community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email address,
+ without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official email address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+scott@bitwise.ninja.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..b111856
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,42 @@
+# Contributing Guidelines
+
+Contributions are always welcome!
+
+**Before spending lots of time on something, ask for feedback on your idea first!**
+
+Please search issues and pull requests before adding something new to avoid duplicating
+efforts and conversations.
+
+
+To make a code contribution to srt2docx
+--------------------------------------
+
+* Fork the srt2docx Github repository and make your changes. Use a well named topic branch for the changes, preferably with uppercase and dashes, use your initials at the beginning of the branch name e.g. `SD-SRT2DOCX-FIXES`. Fork off the `master` branch. Avoid forking from repository work branches as they may get rebased.
+
+* Test your changes as thoroughly as possible, by running the test suite and viewing the coverage reports.
+
+* Please follow the code style for the language you are working in and try to match the general structure of the code. Check that your diff looks as clean and minimal as possible.
+
+* Create a pull request in Github. For now, the "base branch" should be
+ "master", i.e. the pull requests are merged directly to the master branch.
+ In the description:
+
+ - Summarize the change and the motivation for the change.
+
+ To report bugs or request features
+----------------------------------
+
+Use GitHub issues to report bugs or request features:
+
+* Please include a compilation or execution log to help diagnosis.
+
+
+## Installing
+
+Fork and clone the repo, then build and run tests to ensure all is okay before you start anything.
+
+
+## Testing
+
+Please ensure all tests are passing before submitting a pull request (unless you're creating a failing test to increase test coverage or show a problem).
+
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..367d1a6
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,10 @@
+MIT License
+
+Copyright (c) 2024 DreamOS
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2a37d82
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+setup:
+ @python -m venv pyenv; \
+ source ./pyenv/bin/activate; \
+ pip install -r requirements.txt; \
+ echo activate env with: source ./source-me
+requirements:
+ @pip freeze > requirements.txt
+lint:
+ @ruff check .
+fix:
+ @ruff check . --fix
+format:
+ @ruff format .
+git-show:
+ @git log --graph --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%an%C(reset)%C(bold yellow)%d%C(reset) %C(dim white)- %s%C(reset)' --all
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..67cb2ef
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+
+
+
+
+
+Convert srt files to tables in docx
+
+This assumes you have a bash environment.
+
+### Installation
+- Run `make setup`, to initialise environment and create the vitual python environment
+- Source the init script `source source-me`, to activate the python environment
+
+### Running
+- Change settings in `srt2docx_settings.yaml` to your preferences
+- Go to directory with input files
+- execute the script `srt2docx` with the full path, or if you source the `source-me` file it will get added to your path and you can just use `srt2docx` without the path.
+
+### Watermarks
+If you want to use or change the watermark, put the file in the assets directory, and put the file name in the yaml.
+The script will look in the assets directory for all images.
+
+After a sucessful run you should have docx files that share the same base name with the input files except with a `.docx` extension. Errors should be reported to std out.
+
+>Any questions or comments [Scott Dillman](mailto:scott@bitwise.ninja)
+
+Licensed under MIT.
\ No newline at end of file
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..127148f
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,15 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+If there are any vulnerabilities in srt2docx, don't hesitate to _report them_.
+
+1. Use any of the [private contact addresses](https://github.com/ScottDillman/srt2docx#support).
+2. Describe the vulnerability.
+
+- If you have a fix, explain or attach it.
+- In the near time, expect a reply with the required steps. Also, there may be a demand for a pull request which include the fixes.
+
+> You should not disclose the vulnerability publicly if you haven't received an answer in some weeks.
+> If the vulnerability is rejected, you may post it publicly within some hour of rejection, unless the rejection is withdrawn within that time period.
+> After the vulnerability has been fixed, you may disclose the vulnerability details publicly over some days.
diff --git a/assets/flour006.png b/assets/flour006.png
new file mode 100644
index 0000000..7c6b990
Binary files /dev/null and b/assets/flour006.png differ
diff --git a/assets/logo.svg b/assets/logo.svg
new file mode 100644
index 0000000..2a72cac
--- /dev/null
+++ b/assets/logo.svg
@@ -0,0 +1,119 @@
+
+
+
+
diff --git a/assets/logo_header.png b/assets/logo_header.png
new file mode 100644
index 0000000..b33fac1
Binary files /dev/null and b/assets/logo_header.png differ
diff --git a/assets/logo_profile100x100.png b/assets/logo_profile100x100.png
new file mode 100644
index 0000000..ab325fb
Binary files /dev/null and b/assets/logo_profile100x100.png differ
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..8f370ab
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,55 @@
+[project]
+dynamic = ["version"]
+name = "srt2docx"
+authors = [{ name = "Scott Dillman", email = "scott@bitwise.ninja" }]
+maintainers = [{ name = "Scott Dillman", email = "scott@bitwise.ninja" }]
+description = "Script to convert SRT files to DOCX files with tables"
+readme = { file = "README.md", content-type = "text/markdown" }
+license = { file = "LICENSE.md" }
+keywords = ["docx", "srt"]
+
+classifiers = [
+ # How mature is this project? Common values are
+ # 3 - Alpha
+ # 4 - Beta
+ # 5 - Production/Stable
+ "Development Status :: 4 - Beta",
+
+ # Indicate who your project is intended for
+ "Intended Audience :: Course Designers",
+ "Topic :: Content Creation :: Automation Tools",
+
+ # Pick your license as you wish (see also "license" above)
+ "License :: OSI Approved :: MIT License",
+
+ # Specify the Python versions you support here.
+ "Programming Language :: Python :: 3",
+]
+
+dependencies = [
+ "certifi==2024.2.2",
+ "charset-normalizer==3.3.2",
+ "docx==0.2.4",
+ "idna==3.6",
+ "loguru==0.7.2",
+ "lxml==5.2.2",
+ "munch==4.0.0",
+ "pillow==10.3.0",
+ "python-docx==1.1.2",
+ "pytz==2024.1",
+ "PyYAML==6.0.1",
+ "requests==2.31.0",
+ "ruff==0.3.2",
+ "srt==3.5.3",
+ "typing_extensions==4.12.2",
+ "urllib3==2.2.1",
+]
+requires-python = ">=3.8"
+
+
+[project.urls]
+Homepage = "https://dreamcyclestudios.com"
+Documentation = "https://readthedocs.org"
+Repository = "https://github.com/me/spam.git"
+Issues = "https://github.com/me/spam/issues"
+Changelog = "https://github.com/me/spam/blob/master/CHANGELOG.md"
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..c95ae3c
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,16 @@
+certifi==2024.2.2
+charset-normalizer==3.3.2
+docx==0.2.4
+idna==3.6
+loguru==0.7.2
+lxml==5.2.2
+munch==4.0.0
+pillow==10.3.0
+python-docx==1.1.2
+pytz==2024.1
+PyYAML==6.0.1
+requests==2.31.0
+ruff==0.3.2
+srt==3.5.3
+typing_extensions==4.12.2
+urllib3==2.2.1
diff --git a/source-me b/source-me
new file mode 100644
index 0000000..0051d00
--- /dev/null
+++ b/source-me
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+idempotent_path_prepend ()
+{
+ PATH=${PATH//":$1"/} #delete any instances in the middle or at the end
+ PATH=${PATH//"$1:"/} #delete any instances at the beginning
+ export PATH="$1:$PATH" #prepend to beginning
+}
+
+currentDir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+
+idempotent_path_prepend "${PWD}"
+source "${currentDir}/pyenv/bin/activate"
+idempotent_path_prepend "${PWD}"
\ No newline at end of file
diff --git a/srt2docx b/srt2docx
new file mode 100755
index 0000000..d95c865
--- /dev/null
+++ b/srt2docx
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+currentDir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+
+source "${currentDir}/source-me"
+python "${currentDir}/srt2docx.py" $@
\ No newline at end of file
diff --git a/srt2docx.py b/srt2docx.py
new file mode 100644
index 0000000..f3a6af0
--- /dev/null
+++ b/srt2docx.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+"""Script to convert SRT files to DOCX files with tables
+
+Example of end state:
+- https://docs.google.com/document/d/1MqnG5MWRbjZBke9ja5CN-rJGijJnWBrRJa6lLOxMvRQ/edit
+
+SRT format docs
+- https://en.wikipedia.org/wiki/SubRip
+
+DOCX docs
+- https://python-docx.readthedocs.io/en/latest/
+
+Example:
+
+ $ python srt2docx_funcs.py
+
+Todo:
+ * Option to go directly to google docs
+ * Option to combine all files into one docx
+ * add recursion option glob.glob('**/*.txt', recursive=True)
+
+This script reads settings from a srt2docx_settings.yaml file in the same directory as the
+script file. Edit this file to personalize the settings. This only has to be done once.
+
+Generally there is a make file distributed with this script and can be executed as
+follows:
+
+ % make setup
+
+otherwise run the following to initialize the environment:
+
+ % python -m venv pyenv
+ % source ./pyenv/bin/activate
+ % pip install -r requirements.txt
+
+Then activate the environment:
+
+ % activate env with: source ./pyenv/bin/activate
+
+Then in a directory containing the files to be processed run:
+
+$ python srt2docx.py
+
+Output files will have the same name as input files but with the .docx extension.
+
+@Author: Scott Dillman
+@Date: 2024-06-25 22:47
+"""
+
+import srt2docx_funcs
+import argparse
+from loguru import logger
+import inspect
+import os
+
+
+## argument parser
+parser = argparse.ArgumentParser(
+ prog="srt2docx",
+ epilog="Please contact scott@bitwise.ninja with problems/issues",
+ description="Convert srt files to tables in docx",
+)
+
+## update me on major changes
+__version__ = "0.1.0"
+__contact__ = "scott@bitwise.ninja"
+__web__ = "https://dreamcyclesetudios.com"
+
+
+## main entry point
+def main():
+ parser.add_argument(
+ "-v",
+ "--version",
+ action="version",
+ version="%(prog)s " + __version__ + " | {} | {}".format(__contact__, __web__),
+ )
+ args = parser.parse_args()
+
+ ## do any init we need
+ logger.info("Script started: [{}]".format(os.path.realpath(inspect.stack()[0][1])))
+ v = srt2docx_funcs.init(__version__)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/srt2docx_funcs.py b/srt2docx_funcs.py
new file mode 100644
index 0000000..3184d75
--- /dev/null
+++ b/srt2docx_funcs.py
@@ -0,0 +1,151 @@
+# -*- coding: utf-8 -*-
+"""Script to convert SRT files to DOCX files with tables
+
+Example of end state:
+- https://docs.google.com/document/d/1MqnG5MWRbjZBke9ja5CN-rJGijJnWBrRJa6lLOxMvRQ/edit
+
+SRT format docs
+- https://en.wikipedia.org/wiki/SubRip
+
+DOCX docs
+- https://python-docx.readthedocs.io/en/latest/
+
+Example:
+
+ $ python srt2docx_funcs.py
+
+
+@Author: Scott Dillman
+@Date: 2024-06-25 22:47
+"""
+
+import uuid
+import sys
+from munch import munchify
+import yaml
+from loguru import logger
+from pathlib import Path
+from datetime import datetime
+import srt
+import pytz
+from docx import Document
+from docx.shared import Inches
+from docx.enum.text import WD_ALIGN_PARAGRAPH
+import inspect
+import os
+
+
+def readFiles(values) -> list:
+ """read files from cwd"""
+ logger.info("Glob in effect is: [{}]".format(values.settings.filetypes.glob))
+ files = list(Path().glob(values.settings.filetypes.glob))
+ return files
+
+
+def buildDocument(values, subs, title, version):
+ """build the docx document"""
+ document = Document()
+
+ ## add base file name as heading
+ document.add_heading(title, 0)
+
+ ## add SRT data in table
+ table = document.add_table(rows=len(subs), cols=values.settings.table.cols)
+
+ ## create table header
+ hdr_cells = table.rows[0].cells
+ count = 0
+ for h in values.settings.table.headers:
+ hdr_cells[count].text = h
+ count = count + 1
+
+ ## iterate over the subs and add data to table
+ ## TODO: format time
+ for item in subs:
+ row_cells = table.add_row().cells
+ row_cells[0].text = "{}".format(item.start)
+ row_cells[1].text = "{}".format(item.end)
+ row_cells[2].text = "{}".format(item.end - item.start)
+ row_cells[3].text = "{}".format(item.content)
+
+ ## set margins
+ document.sections[0].left_margin = Inches(values.settings.layout.margin_left)
+ document.sections[0].right_margin = Inches(values.settings.layout.margin_right)
+
+ ## add core properties
+ cprops = document.core_properties
+
+ ## add basic document properties from the config yaml
+ cprops.author = values.settings.meta.author
+ cprops.category = values.settings.meta.category
+ cprops.comments = values.settings.meta.comments
+ cprops.content_status = values.settings.meta.content_status
+ cprops.keywords = values.settings.meta.keywords
+ cprops.language = values.settings.meta.language
+ cprops.subject = values.settings.meta.subject
+ cprops.version = values.settings.meta.version
+ cprops.last_modified_by = values.settings.meta.author
+
+ ## UTC is expected, localization happens on the client
+ tz = pytz.timezone("UTC")
+ cprops.created = datetime.now(tz)
+ cprops.modified = datetime.now(tz)
+
+ ## assign a UUID to make this document unique and to tag it with eh str2docx version
+ ## we put the versioon here in case we need to debug a broken file
+ cprops.identifier = "v{}-{}".format(version, str(uuid.uuid4()))
+ logger.info("Document unique id: [{}]", cprops.identifier)
+
+ ## let's add a fun footer
+ if values.settings.footer.show:
+ section = document.sections[0]
+ section.footer_distance = Inches(0.2)
+ footer = section.footer
+ footer_para = footer.paragraphs[0]
+ logo_run = footer_para.add_run()
+
+ ## if you want other watermarks put them in the assets directory
+ ## because that is where we look for this file
+ p = os.path.join(os.path.dirname(os.path.realpath(inspect.stack()[0][1])),"assets")
+ logo_run.add_picture(
+ os.path.join(p,values.settings.footer.watermark),
+ width=Inches(values.settings.footer.width_in),
+ )
+ footer_para.alignment = WD_ALIGN_PARAGRAPH.RIGHT
+
+ ## save the doc out using the base name from read file
+ logger.info("Saving: [{}.docx]".format(title))
+ document.save("{}.docx".format(title))
+
+
+def processFiles(values, files: list, version: str):
+ """transform files"""
+ ## iterate over file list
+ for i in files:
+ logger.info("Processing: [{}]".format(i))
+ subs = []
+ ## open the file for reading
+ with open(i) as f:
+ ## parse the srt file
+ subs = list(srt.parse(f))
+ ## build doc
+ buildDocument(values, subs, Path(i).stem, version)
+
+ return subs
+
+
+def init(version: str) -> dict:
+ """Put any setup that needs to be done here"""
+
+ ## so this beast gets the path to the settings file as an absolute path
+ ## to the running script
+ p=os.path.join(os.path.dirname(os.path.realpath(inspect.stack()[0][1])),"srt2docx_settings.yaml")
+
+ ## load settings
+ values = munchify(yaml.safe_load(open(p)))
+
+ ## do the work
+ files = readFiles(values)
+ srt_data = processFiles(values, files, version)
+
+ return values
diff --git a/srt2docx_settings.yaml b/srt2docx_settings.yaml
new file mode 100644
index 0000000..49e9847
--- /dev/null
+++ b/srt2docx_settings.yaml
@@ -0,0 +1,31 @@
+---
+## this is the settings file
+## widths are in inches
+settings:
+ ## what files to search for
+ ## see globbing rules here : https://docs.python.org/3/library/glob.html
+ filetypes:
+ glob: "*.srt"
+ ## table settings
+ table:
+ cols: 4
+ headers: ["start", "end", "delta", "content"]
+ ## margins
+ layout:
+ margin_left: 0.25
+ margin_right: 0.25
+ ## document meta data
+ meta:
+ author: "someone@example.com"
+ category: "video"
+ comments: "This is just an exmaple xyzzy"
+ content_status: "draft"
+ keywords: "example,test,demo,srt"
+ language: "en"
+ subject: "testing"
+ version: "1.0.0"
+ ## footer settings
+ footer:
+ show: true
+ watermark: "flour006.png"
+ width_in: 0.50
\ No newline at end of file