UniBinaryTextVault 1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- unibinarytextvault-1.1/LICENSE +21 -0
- unibinarytextvault-1.1/PKG-INFO +218 -0
- unibinarytextvault-1.1/README.md +171 -0
- unibinarytextvault-1.1/UniBinaryTextVault.egg-info/PKG-INFO +218 -0
- unibinarytextvault-1.1/UniBinaryTextVault.egg-info/SOURCES.txt +11 -0
- unibinarytextvault-1.1/UniBinaryTextVault.egg-info/dependency_links.txt +1 -0
- unibinarytextvault-1.1/UniBinaryTextVault.egg-info/entry_points.txt +2 -0
- unibinarytextvault-1.1/UniBinaryTextVault.egg-info/requires.txt +1 -0
- unibinarytextvault-1.1/UniBinaryTextVault.egg-info/top_level.txt +1 -0
- unibinarytextvault-1.1/setup.cfg +4 -0
- unibinarytextvault-1.1/setup.py +62 -0
- unibinarytextvault-1.1/tvault/__init__.py +0 -0
- unibinarytextvault-1.1/tvault/tvault.py +351 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 UniBinary
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: UniBinaryTextVault
|
|
3
|
+
Version: 1.1
|
|
4
|
+
Summary: A lightweight text file management system for developers
|
|
5
|
+
Home-page: https://github.com/UniBinary/TextVault
|
|
6
|
+
Author: UniBinary
|
|
7
|
+
Author-email: tp114514251@outlook.com
|
|
8
|
+
Project-URL: Bug Reports, https://github.com/UniBinary/TextVault/issues
|
|
9
|
+
Project-URL: Source, https://github.com/UniBinary/TextVault
|
|
10
|
+
Project-URL: PyPI, https://pypi.org/project/UniBinaryTextVault/
|
|
11
|
+
Keywords: text,vault,file,management,backup,cli,secure
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Classifier: Topic :: Text Processing
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
27
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
28
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
29
|
+
Classifier: Natural Language :: English
|
|
30
|
+
Classifier: Natural Language :: Chinese (Simplified)
|
|
31
|
+
Requires-Python: >=3.7
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
License-File: LICENSE
|
|
34
|
+
Requires-Dist: pyotp>=2.6.0
|
|
35
|
+
Dynamic: author
|
|
36
|
+
Dynamic: author-email
|
|
37
|
+
Dynamic: classifier
|
|
38
|
+
Dynamic: description
|
|
39
|
+
Dynamic: description-content-type
|
|
40
|
+
Dynamic: home-page
|
|
41
|
+
Dynamic: keywords
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
Dynamic: project-url
|
|
44
|
+
Dynamic: requires-dist
|
|
45
|
+
Dynamic: requires-python
|
|
46
|
+
Dynamic: summary
|
|
47
|
+
|
|
48
|
+
# UniBinaryTextVault (TVault)
|
|
49
|
+
|
|
50
|
+
[](https://opensource.org/licenses/MIT)
|
|
51
|
+
[](https://www.python.org/)
|
|
52
|
+
[]()
|
|
53
|
+
|
|
54
|
+
A lightweight, command-line text file management system with automatic backup support.
|
|
55
|
+
|
|
56
|
+
## ✨ Features
|
|
57
|
+
|
|
58
|
+
- **Simple CRUD operations**: Create, read, update, and delete text files
|
|
59
|
+
- **Automatic backups**: Every write operation creates a backup
|
|
60
|
+
- **TOTP support**: Generate time-based one-time passwords from files containing "tt" in their names
|
|
61
|
+
- **Cross-platform**: Works on Linux, macOS, and Windows
|
|
62
|
+
- **No database required**: Uses plain text files
|
|
63
|
+
- **Easy to use**: Simple command-line interface
|
|
64
|
+
|
|
65
|
+
## 📦 Installation
|
|
66
|
+
|
|
67
|
+
### Method 1: Install from PyPI (Recommended)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip3 install UniBinaryTextVault
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
After installation, you need to run the setup:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
# In Python interpreter
|
|
77
|
+
from tvault.dev import install
|
|
78
|
+
install()
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Method 2: Install from source
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git clone https://github.com/UniBinary/TextVault.git
|
|
85
|
+
cd TextVault
|
|
86
|
+
pip3 install .
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 🚀 Quick Start
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Create a new text file
|
|
93
|
+
tvault new notes
|
|
94
|
+
|
|
95
|
+
# Write content to the file
|
|
96
|
+
tvault write notes
|
|
97
|
+
|
|
98
|
+
# Read the file
|
|
99
|
+
tvault read notes
|
|
100
|
+
|
|
101
|
+
# Create a backup
|
|
102
|
+
tvault backup notes
|
|
103
|
+
|
|
104
|
+
# List all files
|
|
105
|
+
tvault list
|
|
106
|
+
|
|
107
|
+
# Get help
|
|
108
|
+
tvault --help
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 📖 Usage
|
|
112
|
+
|
|
113
|
+
### Basic Operations
|
|
114
|
+
|
|
115
|
+
| Command | Description | Example |
|
|
116
|
+
|---------|-------------|---------|
|
|
117
|
+
| `tvault new <file>` | Create a new text file | `tvault new notes` |
|
|
118
|
+
| `tvault read <file>` | Read content from a file | `tvault read notes` |
|
|
119
|
+
| `tvault write <file>` | Write content to a file (with backup) | `tvault write notes` |
|
|
120
|
+
| `tvault backup <file>` | Create a backup of a file | `tvault backup notes` |
|
|
121
|
+
| `tvault recover <file>` | Recover file from backup | `tvault recover notes` |
|
|
122
|
+
| `tvault remove <file>` | Remove a file | `tvault remove notes` |
|
|
123
|
+
| `tvault removebak <file>` | Remove backup file | `tvault removebak notes` |
|
|
124
|
+
| `tvault readbak <file>` | Read content from backup | `tvault readbak notes` |
|
|
125
|
+
| `tvault list` | List all files in vault | `tvault list` |
|
|
126
|
+
| `tvault dumpdb` | Backup entire vault | `tvault dumpdb` |
|
|
127
|
+
| `tvault rmdb` | Remove vault and uninstall | `tvault rmdb` |
|
|
128
|
+
|
|
129
|
+
### TOTP Feature
|
|
130
|
+
|
|
131
|
+
If a filename contains "tt" (e.g., `totp-secret`), TVault can generate TOTP codes:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Create a file with TOTP secret
|
|
135
|
+
tvault new totp-secret
|
|
136
|
+
tvault write totp-secret # Enter your TOTP secret
|
|
137
|
+
|
|
138
|
+
# Read the file to get current TOTP code
|
|
139
|
+
tvault read totp-secret
|
|
140
|
+
# Output: TOTP: 123456
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Advanced Options
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Force overwrite when creating files
|
|
147
|
+
tvault new existing-file --force
|
|
148
|
+
|
|
149
|
+
# Use custom data directory
|
|
150
|
+
tvault new notes --data-dir /path/to/custom/dir
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 🛠️ Development
|
|
154
|
+
|
|
155
|
+
### Project Structure
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
textvault/
|
|
159
|
+
├── tvault/
|
|
160
|
+
│ ├── __init__.py # Package initialization
|
|
161
|
+
│ ├── tvault.py # Main CLI logic
|
|
162
|
+
│ ├── dev.py # Development tools
|
|
163
|
+
│ ├── tvault # Shell wrapper script
|
|
164
|
+
│ └── intros/ # Documentation files
|
|
165
|
+
├── setup.py # Installation configuration
|
|
166
|
+
└── README.md # This file
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Running Tests
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Install development dependencies
|
|
173
|
+
pip3 install -e .
|
|
174
|
+
|
|
175
|
+
# Run the development mode
|
|
176
|
+
python3 -c "from tvault.dev import run; run()"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## 🤝 Contributing
|
|
180
|
+
|
|
181
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
182
|
+
|
|
183
|
+
1. Fork the repository
|
|
184
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
185
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
186
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
187
|
+
5. Open a Pull Request
|
|
188
|
+
|
|
189
|
+
### Reporting Issues
|
|
190
|
+
|
|
191
|
+
If you encounter any issues, please:
|
|
192
|
+
|
|
193
|
+
1. Check the [existing issues](https://github.com/UniBinary/TextVault/issues)
|
|
194
|
+
2. Create a new issue with:
|
|
195
|
+
- A clear description of the problem
|
|
196
|
+
- Steps to reproduce
|
|
197
|
+
- Expected vs actual behavior
|
|
198
|
+
- Your environment (OS, Python version)
|
|
199
|
+
|
|
200
|
+
## 📄 License
|
|
201
|
+
|
|
202
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
203
|
+
|
|
204
|
+
## 📞 Contact
|
|
205
|
+
|
|
206
|
+
- **Author**: UniBinary
|
|
207
|
+
- **Email**: tp114514251@outlook.com
|
|
208
|
+
- **GitHub**: [UniBinary](https://github.com/UniBinary)
|
|
209
|
+
- **Issues**: [GitHub Issues](https://github.com/UniBinary/TextVault/issues)
|
|
210
|
+
|
|
211
|
+
## 🙏 Acknowledgments
|
|
212
|
+
|
|
213
|
+
- Thanks to all contributors and users
|
|
214
|
+
- Built with Python's standard library and [pyotp](https://github.com/pyauth/pyotp)
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
**Note**: This is version 1.0.0.1. The project is actively maintained and improved.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# UniBinaryTextVault (TVault)
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.python.org/)
|
|
5
|
+
[]()
|
|
6
|
+
|
|
7
|
+
A lightweight, command-line text file management system with automatic backup support.
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- **Simple CRUD operations**: Create, read, update, and delete text files
|
|
12
|
+
- **Automatic backups**: Every write operation creates a backup
|
|
13
|
+
- **TOTP support**: Generate time-based one-time passwords from files containing "tt" in their names
|
|
14
|
+
- **Cross-platform**: Works on Linux, macOS, and Windows
|
|
15
|
+
- **No database required**: Uses plain text files
|
|
16
|
+
- **Easy to use**: Simple command-line interface
|
|
17
|
+
|
|
18
|
+
## 📦 Installation
|
|
19
|
+
|
|
20
|
+
### Method 1: Install from PyPI (Recommended)
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip3 install UniBinaryTextVault
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
After installation, you need to run the setup:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
# In Python interpreter
|
|
30
|
+
from tvault.dev import install
|
|
31
|
+
install()
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Method 2: Install from source
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git clone https://github.com/UniBinary/TextVault.git
|
|
38
|
+
cd TextVault
|
|
39
|
+
pip3 install .
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 🚀 Quick Start
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Create a new text file
|
|
46
|
+
tvault new notes
|
|
47
|
+
|
|
48
|
+
# Write content to the file
|
|
49
|
+
tvault write notes
|
|
50
|
+
|
|
51
|
+
# Read the file
|
|
52
|
+
tvault read notes
|
|
53
|
+
|
|
54
|
+
# Create a backup
|
|
55
|
+
tvault backup notes
|
|
56
|
+
|
|
57
|
+
# List all files
|
|
58
|
+
tvault list
|
|
59
|
+
|
|
60
|
+
# Get help
|
|
61
|
+
tvault --help
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 📖 Usage
|
|
65
|
+
|
|
66
|
+
### Basic Operations
|
|
67
|
+
|
|
68
|
+
| Command | Description | Example |
|
|
69
|
+
|---------|-------------|---------|
|
|
70
|
+
| `tvault new <file>` | Create a new text file | `tvault new notes` |
|
|
71
|
+
| `tvault read <file>` | Read content from a file | `tvault read notes` |
|
|
72
|
+
| `tvault write <file>` | Write content to a file (with backup) | `tvault write notes` |
|
|
73
|
+
| `tvault backup <file>` | Create a backup of a file | `tvault backup notes` |
|
|
74
|
+
| `tvault recover <file>` | Recover file from backup | `tvault recover notes` |
|
|
75
|
+
| `tvault remove <file>` | Remove a file | `tvault remove notes` |
|
|
76
|
+
| `tvault removebak <file>` | Remove backup file | `tvault removebak notes` |
|
|
77
|
+
| `tvault readbak <file>` | Read content from backup | `tvault readbak notes` |
|
|
78
|
+
| `tvault list` | List all files in vault | `tvault list` |
|
|
79
|
+
| `tvault dumpdb` | Backup entire vault | `tvault dumpdb` |
|
|
80
|
+
| `tvault rmdb` | Remove vault and uninstall | `tvault rmdb` |
|
|
81
|
+
|
|
82
|
+
### TOTP Feature
|
|
83
|
+
|
|
84
|
+
If a filename contains "tt" (e.g., `totp-secret`), TVault can generate TOTP codes:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Create a file with TOTP secret
|
|
88
|
+
tvault new totp-secret
|
|
89
|
+
tvault write totp-secret # Enter your TOTP secret
|
|
90
|
+
|
|
91
|
+
# Read the file to get current TOTP code
|
|
92
|
+
tvault read totp-secret
|
|
93
|
+
# Output: TOTP: 123456
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Advanced Options
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Force overwrite when creating files
|
|
100
|
+
tvault new existing-file --force
|
|
101
|
+
|
|
102
|
+
# Use custom data directory
|
|
103
|
+
tvault new notes --data-dir /path/to/custom/dir
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 🛠️ Development
|
|
107
|
+
|
|
108
|
+
### Project Structure
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
textvault/
|
|
112
|
+
├── tvault/
|
|
113
|
+
│ ├── __init__.py # Package initialization
|
|
114
|
+
│ ├── tvault.py # Main CLI logic
|
|
115
|
+
│ ├── dev.py # Development tools
|
|
116
|
+
│ ├── tvault # Shell wrapper script
|
|
117
|
+
│ └── intros/ # Documentation files
|
|
118
|
+
├── setup.py # Installation configuration
|
|
119
|
+
└── README.md # This file
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Running Tests
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Install development dependencies
|
|
126
|
+
pip3 install -e .
|
|
127
|
+
|
|
128
|
+
# Run the development mode
|
|
129
|
+
python3 -c "from tvault.dev import run; run()"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 🤝 Contributing
|
|
133
|
+
|
|
134
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
135
|
+
|
|
136
|
+
1. Fork the repository
|
|
137
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
138
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
139
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
140
|
+
5. Open a Pull Request
|
|
141
|
+
|
|
142
|
+
### Reporting Issues
|
|
143
|
+
|
|
144
|
+
If you encounter any issues, please:
|
|
145
|
+
|
|
146
|
+
1. Check the [existing issues](https://github.com/UniBinary/TextVault/issues)
|
|
147
|
+
2. Create a new issue with:
|
|
148
|
+
- A clear description of the problem
|
|
149
|
+
- Steps to reproduce
|
|
150
|
+
- Expected vs actual behavior
|
|
151
|
+
- Your environment (OS, Python version)
|
|
152
|
+
|
|
153
|
+
## 📄 License
|
|
154
|
+
|
|
155
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
156
|
+
|
|
157
|
+
## 📞 Contact
|
|
158
|
+
|
|
159
|
+
- **Author**: UniBinary
|
|
160
|
+
- **Email**: tp114514251@outlook.com
|
|
161
|
+
- **GitHub**: [UniBinary](https://github.com/UniBinary)
|
|
162
|
+
- **Issues**: [GitHub Issues](https://github.com/UniBinary/TextVault/issues)
|
|
163
|
+
|
|
164
|
+
## 🙏 Acknowledgments
|
|
165
|
+
|
|
166
|
+
- Thanks to all contributors and users
|
|
167
|
+
- Built with Python's standard library and [pyotp](https://github.com/pyauth/pyotp)
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
**Note**: This is version 1.0.0.1. The project is actively maintained and improved.
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: UniBinaryTextVault
|
|
3
|
+
Version: 1.1
|
|
4
|
+
Summary: A lightweight text file management system for developers
|
|
5
|
+
Home-page: https://github.com/UniBinary/TextVault
|
|
6
|
+
Author: UniBinary
|
|
7
|
+
Author-email: tp114514251@outlook.com
|
|
8
|
+
Project-URL: Bug Reports, https://github.com/UniBinary/TextVault/issues
|
|
9
|
+
Project-URL: Source, https://github.com/UniBinary/TextVault
|
|
10
|
+
Project-URL: PyPI, https://pypi.org/project/UniBinaryTextVault/
|
|
11
|
+
Keywords: text,vault,file,management,backup,cli,secure
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Classifier: Topic :: Text Processing
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
27
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
28
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
29
|
+
Classifier: Natural Language :: English
|
|
30
|
+
Classifier: Natural Language :: Chinese (Simplified)
|
|
31
|
+
Requires-Python: >=3.7
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
License-File: LICENSE
|
|
34
|
+
Requires-Dist: pyotp>=2.6.0
|
|
35
|
+
Dynamic: author
|
|
36
|
+
Dynamic: author-email
|
|
37
|
+
Dynamic: classifier
|
|
38
|
+
Dynamic: description
|
|
39
|
+
Dynamic: description-content-type
|
|
40
|
+
Dynamic: home-page
|
|
41
|
+
Dynamic: keywords
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
Dynamic: project-url
|
|
44
|
+
Dynamic: requires-dist
|
|
45
|
+
Dynamic: requires-python
|
|
46
|
+
Dynamic: summary
|
|
47
|
+
|
|
48
|
+
# UniBinaryTextVault (TVault)
|
|
49
|
+
|
|
50
|
+
[](https://opensource.org/licenses/MIT)
|
|
51
|
+
[](https://www.python.org/)
|
|
52
|
+
[]()
|
|
53
|
+
|
|
54
|
+
A lightweight, command-line text file management system with automatic backup support.
|
|
55
|
+
|
|
56
|
+
## ✨ Features
|
|
57
|
+
|
|
58
|
+
- **Simple CRUD operations**: Create, read, update, and delete text files
|
|
59
|
+
- **Automatic backups**: Every write operation creates a backup
|
|
60
|
+
- **TOTP support**: Generate time-based one-time passwords from files containing "tt" in their names
|
|
61
|
+
- **Cross-platform**: Works on Linux, macOS, and Windows
|
|
62
|
+
- **No database required**: Uses plain text files
|
|
63
|
+
- **Easy to use**: Simple command-line interface
|
|
64
|
+
|
|
65
|
+
## 📦 Installation
|
|
66
|
+
|
|
67
|
+
### Method 1: Install from PyPI (Recommended)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip3 install UniBinaryTextVault
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
After installation, you need to run the setup:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
# In Python interpreter
|
|
77
|
+
from tvault.dev import install
|
|
78
|
+
install()
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Method 2: Install from source
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git clone https://github.com/UniBinary/TextVault.git
|
|
85
|
+
cd TextVault
|
|
86
|
+
pip3 install .
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 🚀 Quick Start
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Create a new text file
|
|
93
|
+
tvault new notes
|
|
94
|
+
|
|
95
|
+
# Write content to the file
|
|
96
|
+
tvault write notes
|
|
97
|
+
|
|
98
|
+
# Read the file
|
|
99
|
+
tvault read notes
|
|
100
|
+
|
|
101
|
+
# Create a backup
|
|
102
|
+
tvault backup notes
|
|
103
|
+
|
|
104
|
+
# List all files
|
|
105
|
+
tvault list
|
|
106
|
+
|
|
107
|
+
# Get help
|
|
108
|
+
tvault --help
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 📖 Usage
|
|
112
|
+
|
|
113
|
+
### Basic Operations
|
|
114
|
+
|
|
115
|
+
| Command | Description | Example |
|
|
116
|
+
|---------|-------------|---------|
|
|
117
|
+
| `tvault new <file>` | Create a new text file | `tvault new notes` |
|
|
118
|
+
| `tvault read <file>` | Read content from a file | `tvault read notes` |
|
|
119
|
+
| `tvault write <file>` | Write content to a file (with backup) | `tvault write notes` |
|
|
120
|
+
| `tvault backup <file>` | Create a backup of a file | `tvault backup notes` |
|
|
121
|
+
| `tvault recover <file>` | Recover file from backup | `tvault recover notes` |
|
|
122
|
+
| `tvault remove <file>` | Remove a file | `tvault remove notes` |
|
|
123
|
+
| `tvault removebak <file>` | Remove backup file | `tvault removebak notes` |
|
|
124
|
+
| `tvault readbak <file>` | Read content from backup | `tvault readbak notes` |
|
|
125
|
+
| `tvault list` | List all files in vault | `tvault list` |
|
|
126
|
+
| `tvault dumpdb` | Backup entire vault | `tvault dumpdb` |
|
|
127
|
+
| `tvault rmdb` | Remove vault and uninstall | `tvault rmdb` |
|
|
128
|
+
|
|
129
|
+
### TOTP Feature
|
|
130
|
+
|
|
131
|
+
If a filename contains "tt" (e.g., `totp-secret`), TVault can generate TOTP codes:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Create a file with TOTP secret
|
|
135
|
+
tvault new totp-secret
|
|
136
|
+
tvault write totp-secret # Enter your TOTP secret
|
|
137
|
+
|
|
138
|
+
# Read the file to get current TOTP code
|
|
139
|
+
tvault read totp-secret
|
|
140
|
+
# Output: TOTP: 123456
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Advanced Options
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Force overwrite when creating files
|
|
147
|
+
tvault new existing-file --force
|
|
148
|
+
|
|
149
|
+
# Use custom data directory
|
|
150
|
+
tvault new notes --data-dir /path/to/custom/dir
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 🛠️ Development
|
|
154
|
+
|
|
155
|
+
### Project Structure
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
textvault/
|
|
159
|
+
├── tvault/
|
|
160
|
+
│ ├── __init__.py # Package initialization
|
|
161
|
+
│ ├── tvault.py # Main CLI logic
|
|
162
|
+
│ ├── dev.py # Development tools
|
|
163
|
+
│ ├── tvault # Shell wrapper script
|
|
164
|
+
│ └── intros/ # Documentation files
|
|
165
|
+
├── setup.py # Installation configuration
|
|
166
|
+
└── README.md # This file
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Running Tests
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Install development dependencies
|
|
173
|
+
pip3 install -e .
|
|
174
|
+
|
|
175
|
+
# Run the development mode
|
|
176
|
+
python3 -c "from tvault.dev import run; run()"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## 🤝 Contributing
|
|
180
|
+
|
|
181
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
182
|
+
|
|
183
|
+
1. Fork the repository
|
|
184
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
185
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
186
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
187
|
+
5. Open a Pull Request
|
|
188
|
+
|
|
189
|
+
### Reporting Issues
|
|
190
|
+
|
|
191
|
+
If you encounter any issues, please:
|
|
192
|
+
|
|
193
|
+
1. Check the [existing issues](https://github.com/UniBinary/TextVault/issues)
|
|
194
|
+
2. Create a new issue with:
|
|
195
|
+
- A clear description of the problem
|
|
196
|
+
- Steps to reproduce
|
|
197
|
+
- Expected vs actual behavior
|
|
198
|
+
- Your environment (OS, Python version)
|
|
199
|
+
|
|
200
|
+
## 📄 License
|
|
201
|
+
|
|
202
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
203
|
+
|
|
204
|
+
## 📞 Contact
|
|
205
|
+
|
|
206
|
+
- **Author**: UniBinary
|
|
207
|
+
- **Email**: tp114514251@outlook.com
|
|
208
|
+
- **GitHub**: [UniBinary](https://github.com/UniBinary)
|
|
209
|
+
- **Issues**: [GitHub Issues](https://github.com/UniBinary/TextVault/issues)
|
|
210
|
+
|
|
211
|
+
## 🙏 Acknowledgments
|
|
212
|
+
|
|
213
|
+
- Thanks to all contributors and users
|
|
214
|
+
- Built with Python's standard library and [pyotp](https://github.com/pyauth/pyotp)
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
**Note**: This is version 1.0.0.1. The project is actively maintained and improved.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
UniBinaryTextVault.egg-info/PKG-INFO
|
|
5
|
+
UniBinaryTextVault.egg-info/SOURCES.txt
|
|
6
|
+
UniBinaryTextVault.egg-info/dependency_links.txt
|
|
7
|
+
UniBinaryTextVault.egg-info/entry_points.txt
|
|
8
|
+
UniBinaryTextVault.egg-info/requires.txt
|
|
9
|
+
UniBinaryTextVault.egg-info/top_level.txt
|
|
10
|
+
tvault/__init__.py
|
|
11
|
+
tvault/tvault.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyotp>=2.6.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
tvault
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Setup configuration for UniBinaryTextVault
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from setuptools import setup, find_packages
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
# Read the README file
|
|
10
|
+
readme_path = Path(__file__).parent / "README.md"
|
|
11
|
+
long_description = readme_path.read_text(encoding="utf-8") if readme_path.exists() else ""
|
|
12
|
+
|
|
13
|
+
setup(
|
|
14
|
+
name="UniBinaryTextVault",
|
|
15
|
+
version="1.1",
|
|
16
|
+
author="UniBinary",
|
|
17
|
+
author_email="tp114514251@outlook.com",
|
|
18
|
+
description="A lightweight text file management system for developers",
|
|
19
|
+
long_description=long_description,
|
|
20
|
+
long_description_content_type="text/markdown",
|
|
21
|
+
url="https://github.com/UniBinary/TextVault",
|
|
22
|
+
packages=find_packages(),
|
|
23
|
+
package_data={
|
|
24
|
+
"tvault": ["tvault.py",]
|
|
25
|
+
},
|
|
26
|
+
entry_points={
|
|
27
|
+
"console_scripts": [
|
|
28
|
+
"tvault=tvault.tvault:main",
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
classifiers=[
|
|
32
|
+
"Development Status :: 4 - Beta",
|
|
33
|
+
"Intended Audience :: Developers",
|
|
34
|
+
"Intended Audience :: System Administrators",
|
|
35
|
+
"Topic :: Utilities",
|
|
36
|
+
"Topic :: Text Processing",
|
|
37
|
+
"License :: OSI Approved :: MIT License",
|
|
38
|
+
"Programming Language :: Python :: 3",
|
|
39
|
+
"Programming Language :: Python :: 3.7",
|
|
40
|
+
"Programming Language :: Python :: 3.8",
|
|
41
|
+
"Programming Language :: Python :: 3.9",
|
|
42
|
+
"Programming Language :: Python :: 3.10",
|
|
43
|
+
"Programming Language :: Python :: 3.11",
|
|
44
|
+
"Programming Language :: Python :: 3.12",
|
|
45
|
+
"Programming Language :: Python :: 3.13",
|
|
46
|
+
"Operating System :: POSIX :: Linux",
|
|
47
|
+
"Operating System :: MacOS :: MacOS X",
|
|
48
|
+
"Operating System :: Microsoft :: Windows",
|
|
49
|
+
"Natural Language :: English",
|
|
50
|
+
"Natural Language :: Chinese (Simplified)",
|
|
51
|
+
],
|
|
52
|
+
install_requires=[
|
|
53
|
+
"pyotp>=2.6.0",
|
|
54
|
+
],
|
|
55
|
+
python_requires=">=3.7",
|
|
56
|
+
keywords="text, vault, file, management, backup, cli, secure",
|
|
57
|
+
project_urls={
|
|
58
|
+
"Bug Reports": "https://github.com/UniBinary/TextVault/issues",
|
|
59
|
+
"Source": "https://github.com/UniBinary/TextVault",
|
|
60
|
+
"PyPI": "https://pypi.org/project/UniBinaryTextVault/",
|
|
61
|
+
},
|
|
62
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
TextVault (TVault) - A lightweight text file management system
|
|
4
|
+
Version: 1.1
|
|
5
|
+
Author: UniBinary
|
|
6
|
+
License: MIT
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
import shutil
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from pyotp import TOTP
|
|
15
|
+
|
|
16
|
+
class TextVault:
|
|
17
|
+
"""Main TextVault class"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, data_dir=None):
|
|
20
|
+
"""Initialize the vault"""
|
|
21
|
+
if data_dir is None:
|
|
22
|
+
self.data_dir = Path.home() / ".local" / "lib" / "tvault"
|
|
23
|
+
else:
|
|
24
|
+
self.data_dir = Path(data_dir)
|
|
25
|
+
|
|
26
|
+
# Ensure data directory exists
|
|
27
|
+
self.data_dir.mkdir(parents=True, exist_ok=True)
|
|
28
|
+
|
|
29
|
+
def _get_file_path(self, filename):
|
|
30
|
+
"""Get full path for a file (adds .txt extension)"""
|
|
31
|
+
return self.data_dir / f"{filename}.txt"
|
|
32
|
+
|
|
33
|
+
def _get_backup_path(self, filename):
|
|
34
|
+
"""Get backup file path"""
|
|
35
|
+
return self._get_file_path(filename).with_suffix(".txt.bak")
|
|
36
|
+
|
|
37
|
+
def _print_totp_if_needed(self, filename, content):
|
|
38
|
+
"""Print TOTP if filename contains 'tt'"""
|
|
39
|
+
if "tt" in filename:
|
|
40
|
+
try:
|
|
41
|
+
print(f"TOTP: {TOTP(content).now()}")
|
|
42
|
+
except Exception:
|
|
43
|
+
print("Warning: Could not generate TOTP. Printing content instead:")
|
|
44
|
+
print(content)
|
|
45
|
+
else:
|
|
46
|
+
print(content)
|
|
47
|
+
|
|
48
|
+
def create(self, filename, force=False):
|
|
49
|
+
"""Create a new text file"""
|
|
50
|
+
filepath = self._get_file_path(filename)
|
|
51
|
+
|
|
52
|
+
if filepath.exists() and not force:
|
|
53
|
+
response = input(
|
|
54
|
+
"Warning: The file already exists!\n"
|
|
55
|
+
"Press [ENTER] to cancel, or enter any character to overwrite: "
|
|
56
|
+
)
|
|
57
|
+
if not response:
|
|
58
|
+
print("Operation cancelled.")
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
filepath.touch()
|
|
63
|
+
print(f"Created file: {filename}")
|
|
64
|
+
return True
|
|
65
|
+
except Exception as e:
|
|
66
|
+
print(f"Error creating file: {e}")
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
def read(self, filename):
|
|
70
|
+
"""Read content from a file"""
|
|
71
|
+
filepath = self._get_file_path(filename)
|
|
72
|
+
|
|
73
|
+
if not filepath.exists():
|
|
74
|
+
print(f"Error: File '{filename}' does not exist!")
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
content = filepath.read_text(encoding="utf-8")
|
|
79
|
+
self._print_totp_if_needed(filename, content)
|
|
80
|
+
return True
|
|
81
|
+
except Exception as e:
|
|
82
|
+
print(f"Error reading file: {e}")
|
|
83
|
+
return False
|
|
84
|
+
|
|
85
|
+
def write(self, filename):
|
|
86
|
+
"""Write content to a file (with backup)"""
|
|
87
|
+
filepath = self._get_file_path(filename)
|
|
88
|
+
backup_path = self._get_backup_path(filename)
|
|
89
|
+
|
|
90
|
+
if not filepath.exists():
|
|
91
|
+
print(f"Error: File '{filename}' does not exist!")
|
|
92
|
+
return False
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
# Read existing content and create backup
|
|
96
|
+
content = filepath.read_text(encoding="utf-8")
|
|
97
|
+
backup_path.write_text(content, encoding="utf-8")
|
|
98
|
+
|
|
99
|
+
# Show current content
|
|
100
|
+
print("Current content:")
|
|
101
|
+
print("-" * 40)
|
|
102
|
+
print(content)
|
|
103
|
+
print("-" * 40)
|
|
104
|
+
|
|
105
|
+
# Get new content
|
|
106
|
+
print("Enter new content (empty line to finish):")
|
|
107
|
+
lines = []
|
|
108
|
+
while True:
|
|
109
|
+
line = input(">>> ")
|
|
110
|
+
if line == "":
|
|
111
|
+
break
|
|
112
|
+
lines.append(line)
|
|
113
|
+
|
|
114
|
+
# Write new content
|
|
115
|
+
filepath.write_text("\n".join(lines), encoding="utf-8")
|
|
116
|
+
print(f"File '{filename}' updated successfully.")
|
|
117
|
+
return True
|
|
118
|
+
|
|
119
|
+
except Exception as e:
|
|
120
|
+
print(f"Error writing file: {e}")
|
|
121
|
+
return False
|
|
122
|
+
|
|
123
|
+
def backup(self, filename):
|
|
124
|
+
"""Create a backup of a file"""
|
|
125
|
+
filepath = self._get_file_path(filename)
|
|
126
|
+
backup_path = self._get_backup_path(filename)
|
|
127
|
+
|
|
128
|
+
if not filepath.exists():
|
|
129
|
+
print(f"Error: File '{filename}' does not exist!")
|
|
130
|
+
return False
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
content = filepath.read_text(encoding="utf-8")
|
|
134
|
+
backup_path.write_text(content, encoding="utf-8")
|
|
135
|
+
print(f"Backup created for '{filename}'")
|
|
136
|
+
return True
|
|
137
|
+
except Exception as e:
|
|
138
|
+
print(f"Error creating backup: {e}")
|
|
139
|
+
return False
|
|
140
|
+
|
|
141
|
+
def recover(self, filename):
|
|
142
|
+
"""Recover file from backup"""
|
|
143
|
+
filepath = self._get_file_path(filename)
|
|
144
|
+
backup_path = self._get_backup_path(filename)
|
|
145
|
+
|
|
146
|
+
if not backup_path.exists():
|
|
147
|
+
print(f"Error: Backup for '{filename}' does not exist!")
|
|
148
|
+
return False
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
content = backup_path.read_text(encoding="utf-8")
|
|
152
|
+
print("Backup content:")
|
|
153
|
+
print("-" * 40)
|
|
154
|
+
print(content)
|
|
155
|
+
print("-" * 40)
|
|
156
|
+
|
|
157
|
+
response = input("Are you sure you want to restore from backup? (yes/no): ")
|
|
158
|
+
if response.lower() in ["yes", "y", "1"]:
|
|
159
|
+
filepath.write_text(content, encoding="utf-8")
|
|
160
|
+
backup_path.unlink() # Remove backup after recovery
|
|
161
|
+
print(f"File '{filename}' recovered from backup.")
|
|
162
|
+
return True
|
|
163
|
+
else:
|
|
164
|
+
print("Recovery cancelled.")
|
|
165
|
+
return False
|
|
166
|
+
|
|
167
|
+
except Exception as e:
|
|
168
|
+
print(f"Error recovering file: {e}")
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
def remove(self, filename):
|
|
172
|
+
"""Remove a file"""
|
|
173
|
+
filepath = self._get_file_path(filename)
|
|
174
|
+
|
|
175
|
+
if not filepath.exists():
|
|
176
|
+
print(f"Error: File '{filename}' does not exist!")
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
try:
|
|
180
|
+
filepath.unlink()
|
|
181
|
+
print(f"File '{filename}' removed.")
|
|
182
|
+
return True
|
|
183
|
+
except Exception as e:
|
|
184
|
+
print(f"Error removing file: {e}")
|
|
185
|
+
return False
|
|
186
|
+
|
|
187
|
+
def remove_backup(self, filename):
|
|
188
|
+
"""Remove a backup file"""
|
|
189
|
+
backup_path = self._get_backup_path(filename)
|
|
190
|
+
|
|
191
|
+
if not backup_path.exists():
|
|
192
|
+
print(f"Error: Backup for '{filename}' does not exist!")
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
try:
|
|
196
|
+
backup_path.unlink()
|
|
197
|
+
print(f"Backup for '{filename}' removed.")
|
|
198
|
+
return True
|
|
199
|
+
except Exception as e:
|
|
200
|
+
print(f"Error removing backup: {e}")
|
|
201
|
+
return False
|
|
202
|
+
|
|
203
|
+
def read_backup(self, filename):
|
|
204
|
+
"""Read content from backup"""
|
|
205
|
+
backup_path = self._get_backup_path(filename)
|
|
206
|
+
|
|
207
|
+
if not backup_path.exists():
|
|
208
|
+
print(f"Error: Backup for '{filename}' does not exist!")
|
|
209
|
+
return False
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
content = backup_path.read_text(encoding="utf-8")
|
|
213
|
+
self._print_totp_if_needed(filename, content)
|
|
214
|
+
return True
|
|
215
|
+
except Exception as e:
|
|
216
|
+
print(f"Error reading backup: {e}")
|
|
217
|
+
return False
|
|
218
|
+
|
|
219
|
+
def list_files(self):
|
|
220
|
+
"""List all files in the vault"""
|
|
221
|
+
try:
|
|
222
|
+
files = list(self.data_dir.glob("*.txt"))
|
|
223
|
+
if not files:
|
|
224
|
+
print("No files in vault.")
|
|
225
|
+
return True
|
|
226
|
+
|
|
227
|
+
print(f"Files in vault ({len(files)} total):")
|
|
228
|
+
print("-" * 40)
|
|
229
|
+
for file in sorted(files):
|
|
230
|
+
size = file.stat().st_size
|
|
231
|
+
mtime = datetime.fromtimestamp(file.stat().st_mtime)
|
|
232
|
+
backup_exists = file.with_suffix(".txt.bak").exists()
|
|
233
|
+
backup_marker = "✓" if backup_exists else " "
|
|
234
|
+
print(f"{backup_marker} {file.stem:20} {size:6} bytes {mtime:%Y-%m-%d %H:%M}")
|
|
235
|
+
return True
|
|
236
|
+
|
|
237
|
+
except Exception as e:
|
|
238
|
+
print(f"Error listing files: {e}")
|
|
239
|
+
return False
|
|
240
|
+
|
|
241
|
+
def backup_vault(self):
|
|
242
|
+
"""Backup the entire vault"""
|
|
243
|
+
try:
|
|
244
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
245
|
+
backup_dir = Path.home() / f"tvault_backup_{timestamp}"
|
|
246
|
+
|
|
247
|
+
shutil.copytree(self.data_dir, backup_dir)
|
|
248
|
+
print(f"Vault backed up to: {backup_dir}")
|
|
249
|
+
return True
|
|
250
|
+
except Exception as e:
|
|
251
|
+
print(f"Error backing up vault: {e}")
|
|
252
|
+
return False
|
|
253
|
+
|
|
254
|
+
def remove_vault(self):
|
|
255
|
+
"""Remove the entire vault"""
|
|
256
|
+
response = input(
|
|
257
|
+
f"WARNING: This will remove ALL files under current data directory (current dir: {self.data_dir})!\n"
|
|
258
|
+
"Type 'confirm-delete-all' to proceed: "
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
if response == "confirm-delete-all":
|
|
262
|
+
try:
|
|
263
|
+
# Remove vault directory
|
|
264
|
+
if self.data_dir.exists():
|
|
265
|
+
shutil.rmtree(self.data_dir)
|
|
266
|
+
|
|
267
|
+
print("vault removed successfully.")
|
|
268
|
+
return True
|
|
269
|
+
except Exception as e:
|
|
270
|
+
print(f"Error removing vault: {e}")
|
|
271
|
+
return False
|
|
272
|
+
else:
|
|
273
|
+
print("Operation cancelled.")
|
|
274
|
+
return False
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def main():
|
|
278
|
+
"""Main entry point"""
|
|
279
|
+
parser = ArgumentParser(
|
|
280
|
+
description="Text Vault - A lightweight text file management system",
|
|
281
|
+
formatter_class=ArgumentDefaultsHelpFormatter
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
parser.add_argument(
|
|
285
|
+
"operation",
|
|
286
|
+
choices=[
|
|
287
|
+
"create", "read", "write", "backup", "recover",
|
|
288
|
+
"remove", "removebak", "readbak", "list", "backup-vault", "remove-vault"
|
|
289
|
+
],
|
|
290
|
+
help="Operation to perform"
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
parser.add_argument(
|
|
294
|
+
"filename",
|
|
295
|
+
nargs="?",
|
|
296
|
+
help="Filename (without .txt extension)"
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
parser.add_argument(
|
|
300
|
+
"--force",
|
|
301
|
+
action="store_true",
|
|
302
|
+
help="Force overwrite when creating new files"
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
parser.add_argument(
|
|
306
|
+
"--data-dir",
|
|
307
|
+
help="Custom data directory (default: ~/.local/lib/tvault)"
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
args = parser.parse_args()
|
|
311
|
+
|
|
312
|
+
# Validate filename for operations that need it
|
|
313
|
+
operations_needing_filename = [
|
|
314
|
+
"create", "read", "write", "backup", "recover",
|
|
315
|
+
"remove", "removebak", "readbak"
|
|
316
|
+
]
|
|
317
|
+
|
|
318
|
+
if args.operation in operations_needing_filename and not args.filename:
|
|
319
|
+
print(f"Error: Operation '{args.operation}' requires a filename!")
|
|
320
|
+
parser.print_help()
|
|
321
|
+
return 1
|
|
322
|
+
|
|
323
|
+
# Initialize vault
|
|
324
|
+
tvault = TextVault(args.data_dir)
|
|
325
|
+
|
|
326
|
+
# Execute operation
|
|
327
|
+
operations = {
|
|
328
|
+
"create": lambda: tvault.create(args.filename, args.force),
|
|
329
|
+
"read": lambda: tvault.read(args.filename),
|
|
330
|
+
"write": lambda: tvault.write(args.filename),
|
|
331
|
+
"backup": lambda: tvault.backup(args.filename),
|
|
332
|
+
"recover": lambda: tvault.recover(args.filename),
|
|
333
|
+
"remove": lambda: tvault.remove(args.filename),
|
|
334
|
+
"removebak": lambda: tvault.remove_backup(args.filename),
|
|
335
|
+
"readbak": lambda: tvault.read_backup(args.filename),
|
|
336
|
+
"list": lambda: tvault.list_files(),
|
|
337
|
+
"backup-vault": lambda: tvault.backup_vault(),
|
|
338
|
+
"remove-vault": lambda: tvault.remove_vault(),
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
success = operations.get(args.operation, lambda: False)()
|
|
342
|
+
return 0 if success else 1
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
if __name__ == "__main__":
|
|
346
|
+
# Prevent direct imports
|
|
347
|
+
sys.exit(main())
|
|
348
|
+
else:
|
|
349
|
+
# Allow imports for testing purposes
|
|
350
|
+
# raise ImportError("This module should not to be imported directly, use the 'tvault' command instead.")
|
|
351
|
+
pass # Allow imports for testing and development
|