Compare commits
	
		
			9 Commits
		
	
	
		
			v1.0.7
			...
			3fda737af2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3fda737af2 | |||
| 
						
						
							
						
						8cf3d4dda8
	
				 | 
					
					
						|||
| 
						
						
							
						
						2e18921a27
	
				 | 
					
					
						|||
| 
						
						
							
						
						f1efb1d67c
	
				 | 
					
					
						|||
| 
						
						
							
						
						457ede5b62
	
				 | 
					
					
						|||
| 
						
						
							
						
						7eb724d01f
	
				 | 
					
					
						|||
| 
						
						
							
						
						189bbb0874
	
				 | 
					
					
						|||
| 
						
						
							
						
						68da5f9658
	
				 | 
					
					
						|||
| 
						
						
							
						
						83cd0b722b
	
				 | 
					
					
						
@@ -1,14 +1,14 @@
 | 
			
		||||
[General]
 | 
			
		||||
BaseDir = "/mnt/media"
 | 
			
		||||
BaseDir = "/mnt/Media"
 | 
			
		||||
Format = "mkv"
 | 
			
		||||
TempBaseDir = "/tmp/nre"
 | 
			
		||||
EnableConsole = true
 | 
			
		||||
 | 
			
		||||
[WatchFolder]
 | 
			
		||||
Path = "/mnt/watched"
 | 
			
		||||
Path = "/mnt/Watched"
 | 
			
		||||
PollingInterval = 10
 | 
			
		||||
UsePolling = false 
 | 
			
		||||
UseInotify = true
 | 
			
		||||
UseInotify = false 
 | 
			
		||||
 | 
			
		||||
[N_m3u8DLRE]
 | 
			
		||||
Path = "nre"
 | 
			
		||||
@@ -195,6 +195,10 @@ func getDownloadCommand(item Item, mpdPath string, tempDir string) string {
 | 
			
		||||
 | 
			
		||||
	command += fmt.Sprintf(" --tmp-dir \"%s\"", tempDir)
 | 
			
		||||
 | 
			
		||||
	if globalSpeedLimit != "" {
 | 
			
		||||
		command += fmt.Sprintf(" -R %s", globalSpeedLimit)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Println(command)
 | 
			
		||||
 | 
			
		||||
	return command
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,11 @@ func handleRoot(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
			CurrentFile string
 | 
			
		||||
			Paused      bool
 | 
			
		||||
		}
 | 
			
		||||
	}{jobsInfo})
 | 
			
		||||
		GlobalSpeedLimit string
 | 
			
		||||
	}{
 | 
			
		||||
		Jobs:             jobsInfo,
 | 
			
		||||
		GlobalSpeedLimit: globalSpeedLimit,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.LogError("Handle Root", fmt.Sprintf("Error executing template: %v", err))
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
@@ -443,3 +447,32 @@ func broadcast(filename string, message []byte) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func handleSetSpeedLimit(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	logger.LogInfo("Set Speed Limit", "Received request to set speed limit")
 | 
			
		||||
 | 
			
		||||
	if r.Method != http.MethodPost {
 | 
			
		||||
		logger.LogError("Set Speed Limit", "Invalid method")
 | 
			
		||||
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var requestData struct {
 | 
			
		||||
		SpeedLimit string `json:"speedLimit"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := json.NewDecoder(r.Body).Decode(&requestData); err != nil {
 | 
			
		||||
		logger.LogError("Set Speed Limit", "Invalid request body")
 | 
			
		||||
		http.Error(w, "Invalid request", http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if requestData.SpeedLimit == "unlimited" {
 | 
			
		||||
		globalSpeedLimit = ""
 | 
			
		||||
	} else {
 | 
			
		||||
		globalSpeedLimit = requestData.SpeedLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	logger.LogInfo("Set Speed Limit", fmt.Sprintf("Global speed limit set to: %s", globalSpeedLimit))
 | 
			
		||||
	w.WriteHeader(http.StatusOK)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,8 @@ var templates *template.Template
 | 
			
		||||
//go:embed templates
 | 
			
		||||
var templateFS embed.FS
 | 
			
		||||
 | 
			
		||||
var globalSpeedLimit string
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	if err := os.MkdirAll(uploadDir, 0755); err != nil {
 | 
			
		||||
		fmt.Printf("Error creating upload directory: %v\n", err)
 | 
			
		||||
@@ -70,6 +72,8 @@ func main() {
 | 
			
		||||
		}
 | 
			
		||||
		processItems(*inputFile, items)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	http.HandleFunc("/set-speed-limit", handleSetSpeedLimit)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func startWebServer() {
 | 
			
		||||
@@ -83,6 +87,7 @@ func startWebServer() {
 | 
			
		||||
	http.HandleFunc("/resume", handleResume)
 | 
			
		||||
	http.HandleFunc("/clear-completed", handleClearCompleted)
 | 
			
		||||
	http.HandleFunc("/ws", handleWebSocket)
 | 
			
		||||
	http.HandleFunc("/set-speed-limit", handleSetSpeedLimit)
 | 
			
		||||
 | 
			
		||||
	logger.LogInfo("Main", "Starting web server on http://0.0.0.0:8080")
 | 
			
		||||
	http.ListenAndServe(":8080", nil)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,6 @@
 | 
			
		||||
        input[type="file"], input[type="submit"] {
 | 
			
		||||
            background-color: #2d2d2d;
 | 
			
		||||
            color: #d4d4d4;
 | 
			
		||||
            border: 1px solid #444;
 | 
			
		||||
            padding: 8px 12px;
 | 
			
		||||
            border-radius: 4px;
 | 
			
		||||
            margin-bottom: 10px;
 | 
			
		||||
@@ -77,6 +76,11 @@
 | 
			
		||||
        .paused {
 | 
			
		||||
            color: #ffa500;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit {
 | 
			
		||||
            font-size: 1em;
 | 
			
		||||
            color: #a0a0a0;
 | 
			
		||||
            margin-top: 10px;
 | 
			
		||||
        }
 | 
			
		||||
        @media (max-width: 600px) {
 | 
			
		||||
            body {
 | 
			
		||||
                padding: 10px;
 | 
			
		||||
@@ -107,6 +111,94 @@
 | 
			
		||||
        #clear-completed:hover {
 | 
			
		||||
            background-color: #d32f2f;
 | 
			
		||||
        }
 | 
			
		||||
        /* New CSS for speed limit form */
 | 
			
		||||
        .settings-section {
 | 
			
		||||
            margin-top: 30px;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-form {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            justify-content: space-between;
 | 
			
		||||
            gap: 10px;
 | 
			
		||||
            margin-bottom: 20px;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-form .form-group {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            gap: 10px;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-form input[type="number"],
 | 
			
		||||
        .speed-limit-form select,
 | 
			
		||||
        .speed-limit-form button {
 | 
			
		||||
            background-color: #2d2d2d;
 | 
			
		||||
            color: #d4d4d4;
 | 
			
		||||
            border: 1px solid #444;
 | 
			
		||||
            padding: 8px 12px;
 | 
			
		||||
            border-radius: 4px;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-form button {
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
            background-color: #4CAF50;
 | 
			
		||||
            color: white;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-form button:hover {
 | 
			
		||||
            background-color: #45a049;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-container {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            margin-bottom: 20px;
 | 
			
		||||
            background-color: #2d2d2d;
 | 
			
		||||
            padding: 8px 12px;
 | 
			
		||||
            border-radius: 4px;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-container .form-group {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            gap: 10px;
 | 
			
		||||
            width: 100%;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-container input[type="number"] {
 | 
			
		||||
            background-color: #2d2d2d;
 | 
			
		||||
            color: #d4d4d4;
 | 
			
		||||
            border: 1px solid #444;
 | 
			
		||||
            padding: 8px 12px;
 | 
			
		||||
            border-radius: 4px;
 | 
			
		||||
            height: 40px;
 | 
			
		||||
            box-sizing: border-box;
 | 
			
		||||
            flex-grow: 1;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-container select,
 | 
			
		||||
        .speed-limit-container button {
 | 
			
		||||
            background-color: #2d2d2d;
 | 
			
		||||
            color: #d4d4d4;
 | 
			
		||||
            border: 1px solid #444;
 | 
			
		||||
            padding: 8px 12px;
 | 
			
		||||
            border-radius: 4px;
 | 
			
		||||
            height: 40px;
 | 
			
		||||
            box-sizing: border-box;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-container button {
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
            background-color: #4CAF50;
 | 
			
		||||
            color: white;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-container button:hover {
 | 
			
		||||
            background-color: #45a049;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-container .speed-limit {
 | 
			
		||||
            color: #d4d4d4;
 | 
			
		||||
            margin-left: auto;
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
        }
 | 
			
		||||
        .speed-limit-container .speed-limit span {
 | 
			
		||||
            margin-left: 5px;
 | 
			
		||||
        }
 | 
			
		||||
        .current-speed-limit {
 | 
			
		||||
            color: #d4d4d4;
 | 
			
		||||
            margin-top: 10px;
 | 
			
		||||
        }
 | 
			
		||||
    </style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
@@ -135,6 +227,23 @@
 | 
			
		||||
        {{end}}
 | 
			
		||||
    </ul>
 | 
			
		||||
    <button id="clear-completed" onclick="clearCompleted()">Clear Completed Jobs</button>
 | 
			
		||||
    
 | 
			
		||||
    <div class="settings-section">
 | 
			
		||||
        <h2>Settings</h2>
 | 
			
		||||
        <div class="speed-limit-container">
 | 
			
		||||
            <div class="form-group">
 | 
			
		||||
                <label for="speedLimitValue">Speed Limit:</label>
 | 
			
		||||
                <input type="number" id="speedLimitValue" name="speedLimitValue" min="0" step="0.01" required>
 | 
			
		||||
                <select id="speedLimitUnit" name="speedLimitUnit">
 | 
			
		||||
                    <option value="GBps">GBps</option>
 | 
			
		||||
                    <option value="MBps" selected>MBps</option>
 | 
			
		||||
                    <option value="KBps">KBps</option>
 | 
			
		||||
                </select>
 | 
			
		||||
                <button type="button" onclick="updateSpeedLimit(event)">Set Limit</button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <script>
 | 
			
		||||
        function clearCompleted() {
 | 
			
		||||
            fetch('/clear-completed', { method: 'POST' })
 | 
			
		||||
@@ -147,6 +256,54 @@
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        function updateSpeedLimit(event) {
 | 
			
		||||
            event.preventDefault();
 | 
			
		||||
 | 
			
		||||
            const speedLimitValue = document.getElementById('speedLimitValue').value;
 | 
			
		||||
            const speedLimitUnit = document.getElementById('speedLimitUnit').value;
 | 
			
		||||
            const speedLimit = speedLimitValue === "0" ? "unlimited" : speedLimitValue + speedLimitUnit;
 | 
			
		||||
 | 
			
		||||
            if (!validateSpeedLimit(speedLimitValue)) {
 | 
			
		||||
                alert('Please enter a valid speed limit.');
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fetch('/set-speed-limit', {
 | 
			
		||||
                method: 'POST',
 | 
			
		||||
                headers: {
 | 
			
		||||
                    'Content-Type': 'application/json',
 | 
			
		||||
                },
 | 
			
		||||
                body: JSON.stringify({ speedLimit }),
 | 
			
		||||
            }).then(response => {
 | 
			
		||||
                if (response.ok) {
 | 
			
		||||
                    alert('Speed limit updated successfully');
 | 
			
		||||
                    document.getElementById('currentSpeedLimit').textContent = speedLimit;
 | 
			
		||||
                } else {
 | 
			
		||||
                    alert('Failed to update speed limit');
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        function validateSpeedLimit(value) {
 | 
			
		||||
            const number = parseFloat(value);
 | 
			
		||||
            return !isNaN(number) && number >= 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        document.addEventListener('DOMContentLoaded', function() {
 | 
			
		||||
            const currentSpeedLimit = "{{if .GlobalSpeedLimit}}{{.GlobalSpeedLimit}}{{else}}0{{end}}";
 | 
			
		||||
            const speedLimitValueInput = document.getElementById('speedLimitValue');
 | 
			
		||||
            const speedLimitUnitSelect = document.getElementById('speedLimitUnit');
 | 
			
		||||
 | 
			
		||||
            const match = currentSpeedLimit.match(/(\d+(\.\d+)?)([A-Za-z]+)/);
 | 
			
		||||
            if (match) {
 | 
			
		||||
                speedLimitValueInput.value = match[1];
 | 
			
		||||
                speedLimitUnitSelect.value = match[3];
 | 
			
		||||
            } else {
 | 
			
		||||
                speedLimitValueInput.value = "0"; 
 | 
			
		||||
                speedLimitUnitSelect.value = "MBps";
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    </script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user