webtap-tool 0.1.4__py3-none-any.whl → 0.2.0__py3-none-any.whl

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.

Potentially problematic release.


This version of webtap-tool might be problematic. Click here for more details.

webtap/services/setup.py DELETED
@@ -1,229 +0,0 @@
1
- """Setup service for installing WebTap components."""
2
-
3
- import os
4
- import json
5
- import logging
6
- from pathlib import Path
7
- from typing import Dict, Any
8
-
9
- import requests
10
-
11
- logger = logging.getLogger(__name__)
12
-
13
-
14
- class SetupService:
15
- """Service for installing WebTap components."""
16
-
17
- # GitHub URLs
18
- FILTERS_URL = "https://raw.githubusercontent.com/angelsen/tap-tools/main/packages/webtap/data/filters.json"
19
- EXTENSION_BASE_URL = "https://raw.githubusercontent.com/angelsen/tap-tools/main/packages/webtap/extension"
20
- EXTENSION_FILES = ["manifest.json", "popup.html", "popup.js"]
21
-
22
- def install_filters(self, force: bool = False) -> Dict[str, Any]:
23
- """Install filters to .webtap/filters.json.
24
-
25
- Args:
26
- force: Overwrite existing file
27
-
28
- Returns:
29
- Dict with success, message, path, details
30
- """
31
- # Same path that FilterManager uses
32
- target_path = Path.cwd() / ".webtap" / "filters.json"
33
-
34
- # Check if exists
35
- if target_path.exists() and not force:
36
- return {
37
- "success": False,
38
- "message": f"Filters already exist at {target_path}",
39
- "path": str(target_path),
40
- "details": "Use --force to overwrite",
41
- }
42
-
43
- # Download from GitHub
44
- try:
45
- logger.info(f"Downloading filters from {self.FILTERS_URL}")
46
- response = requests.get(self.FILTERS_URL, timeout=10)
47
- response.raise_for_status()
48
-
49
- # Validate it's proper JSON
50
- filters_data = json.loads(response.text)
51
-
52
- # Quick validation - should have dict structure
53
- if not isinstance(filters_data, dict):
54
- return {
55
- "success": False,
56
- "message": "Invalid filter format - expected JSON object",
57
- "path": None,
58
- "details": None,
59
- }
60
-
61
- # Count categories for user feedback
62
- category_count = len(filters_data)
63
-
64
- # Create directory and save
65
- target_path.parent.mkdir(parents=True, exist_ok=True)
66
- target_path.write_text(response.text)
67
-
68
- logger.info(f"Saved {category_count} filter categories to {target_path}")
69
-
70
- return {
71
- "success": True,
72
- "message": f"Downloaded {category_count} filter categories",
73
- "path": str(target_path),
74
- "details": f"Categories: {', '.join(filters_data.keys())}",
75
- }
76
-
77
- except requests.RequestException as e:
78
- logger.error(f"Network error downloading filters: {e}")
79
- return {"success": False, "message": f"Network error: {e}", "path": None, "details": None}
80
- except json.JSONDecodeError as e:
81
- logger.error(f"Invalid JSON in filters: {e}")
82
- return {"success": False, "message": f"Invalid JSON format: {e}", "path": None, "details": None}
83
- except Exception as e:
84
- logger.error(f"Unexpected error: {e}")
85
- return {"success": False, "message": f"Failed to download filters: {e}", "path": None, "details": None}
86
-
87
- def install_extension(self, force: bool = False) -> Dict[str, Any]:
88
- """Install Chrome extension to ~/.config/webtap/extension/.
89
-
90
- Args:
91
- force: Overwrite existing files
92
-
93
- Returns:
94
- Dict with success, message, path, details
95
- """
96
- # XDG config directory for Linux
97
- target_dir = Path.home() / ".config" / "webtap" / "extension"
98
-
99
- # Check if exists (manifest.json is required file)
100
- if (target_dir / "manifest.json").exists() and not force:
101
- return {
102
- "success": False,
103
- "message": f"Extension already exists at {target_dir}",
104
- "path": str(target_dir),
105
- "details": "Use --force to overwrite",
106
- }
107
-
108
- # Create directory
109
- target_dir.mkdir(parents=True, exist_ok=True)
110
-
111
- # Download each file
112
- downloaded = []
113
- failed = []
114
-
115
- for filename in self.EXTENSION_FILES:
116
- url = f"{self.EXTENSION_BASE_URL}/{filename}"
117
- target_file = target_dir / filename
118
-
119
- try:
120
- logger.info(f"Downloading {filename}")
121
- response = requests.get(url, timeout=10)
122
- response.raise_for_status()
123
-
124
- # For manifest.json, validate it's proper JSON
125
- if filename == "manifest.json":
126
- json.loads(response.text)
127
-
128
- target_file.write_text(response.text)
129
- downloaded.append(filename)
130
-
131
- except Exception as e:
132
- logger.error(f"Failed to download {filename}: {e}")
133
- failed.append(filename)
134
-
135
- # Determine success level
136
- if not downloaded:
137
- return {
138
- "success": False,
139
- "message": "Failed to download any extension files",
140
- "path": None,
141
- "details": "Check network connection and try again",
142
- }
143
-
144
- if failed:
145
- # Partial success - some files downloaded
146
- return {
147
- "success": True, # Partial is still success
148
- "message": f"Downloaded {len(downloaded)}/{len(self.EXTENSION_FILES)} files",
149
- "path": str(target_dir),
150
- "details": f"Failed: {', '.join(failed)}",
151
- }
152
-
153
- return {
154
- "success": True,
155
- "message": "Downloaded Chrome extension",
156
- "path": str(target_dir),
157
- "details": f"Files: {', '.join(downloaded)}",
158
- }
159
-
160
- def install_chrome_wrapper(self, force: bool = False) -> Dict[str, Any]:
161
- """Install Chrome wrapper script for debugging.
162
-
163
- Args:
164
- force: Overwrite existing script
165
-
166
- Returns:
167
- Dict with success, message, path, details
168
- """
169
- target_path = Path.home() / ".local" / "bin" / "wrappers" / "google-chrome-stable"
170
-
171
- if target_path.exists() and not force:
172
- return {
173
- "success": False,
174
- "message": "Chrome wrapper already exists",
175
- "path": str(target_path),
176
- "details": "Use --force to overwrite",
177
- }
178
-
179
- wrapper_script = """#!/bin/bash
180
- # Chrome wrapper using bindfs for perfect state sync with debug port
181
-
182
- DEBUG_DIR="$HOME/.config/google-chrome-debug"
183
- REAL_DIR="$HOME/.config/google-chrome"
184
-
185
- # Check if bindfs is installed
186
- if ! command -v bindfs &>/dev/null; then
187
- echo "Error: bindfs not installed. Install with: yay -S bindfs" >&2
188
- exit 1
189
- fi
190
-
191
- # Mount real profile via bindfs if not already mounted
192
- if ! mountpoint -q "$DEBUG_DIR" 2>/dev/null; then
193
- mkdir -p "$DEBUG_DIR"
194
- if ! bindfs --no-allow-other "$REAL_DIR" "$DEBUG_DIR"; then
195
- echo "Error: Failed to mount Chrome profile via bindfs" >&2
196
- exit 1
197
- fi
198
- echo "Chrome debug profile mounted. To unmount: fusermount -u $DEBUG_DIR" >&2
199
- fi
200
-
201
- # Launch Chrome with debugging on bindfs mount
202
- exec /usr/bin/google-chrome-stable \\
203
- --remote-debugging-port=9222 \\
204
- --remote-allow-origins='*' \\
205
- --user-data-dir="$DEBUG_DIR" \\
206
- "$@"
207
- """
208
-
209
- # Create directory and save
210
- target_path.parent.mkdir(parents=True, exist_ok=True)
211
- target_path.write_text(wrapper_script)
212
- target_path.chmod(0o755) # Make executable
213
-
214
- # Check PATH
215
- path_dirs = os.environ.get("PATH", "").split(":")
216
- wrapper_dir = str(target_path.parent)
217
- in_path = wrapper_dir in path_dirs
218
-
219
- logger.info(f"Installed Chrome wrapper to {target_path}")
220
-
221
- return {
222
- "success": True,
223
- "message": "Installed Chrome wrapper script",
224
- "path": str(target_path),
225
- "details": "Already in PATH ✓" if in_path else "Add to PATH",
226
- }
227
-
228
-
229
- __all__ = ["SetupService"]