diff --git a/src/cmd/main.go b/src/cmd/main.go
index e4e9f34..1bf2699 100644
--- a/src/cmd/main.go
+++ b/src/cmd/main.go
@@ -21,6 +21,7 @@ package main
import (
"git.weirdcat.su/weirdcat/auto-attendance/internal/config"
+ "git.weirdcat.su/weirdcat/auto-attendance/internal/linkvalidator"
"git.weirdcat.su/weirdcat/auto-attendance/internal/logger"
"go.uber.org/fx"
)
@@ -30,6 +31,7 @@ func main() {
fx.Provide(
config.NewConfig,
logger.NewLogger,
+ linkvalidator.NewLinkValidator,
),
fx.Invoke(func(log *logger.Logger) {
log.Info("Starting application...");
diff --git a/src/internal/linkvalidator/linkvalidator.go b/src/internal/linkvalidator/linkvalidator.go
new file mode 100644
index 0000000..b4e8173
--- /dev/null
+++ b/src/internal/linkvalidator/linkvalidator.go
@@ -0,0 +1,88 @@
+// Copyright (c) 2025 Nikolai Papin
+//
+// This file is part of the Auto Attendance app that looks for
+// self-attend QR-codes during lectures and opens their URLs in your
+// browser.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+// the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+package linkvalidator
+
+import (
+ "net/url"
+ "strings"
+
+ "git.weirdcat.su/weirdcat/auto-attendance/internal/config"
+ "git.weirdcat.su/weirdcat/auto-attendance/internal/logger"
+)
+
+type LinkValidator interface {
+ ValidateLink(string) (token string, ok bool)
+}
+
+type linkValidatorImpl struct {
+ config *config.Config
+ log *logger.Logger
+}
+
+// ValidateLink implements LinkValidator.
+func (v *linkValidatorImpl) ValidateLink(rawURL string) (token string, ok bool) {
+ if rawURL == "" {
+ v.log.Debug("Empty URL provided for validation")
+ return "", false
+ }
+
+ parsedURL, err := url.Parse(rawURL)
+ if err != nil {
+ v.log.Debug("Failed to parse URL", "url", rawURL, "error", err)
+ return "", false
+ }
+
+ if v.config.Communication.QrUrl != "" {
+ expectedURL, err := url.Parse(v.config.Communication.QrUrl)
+ if err == nil {
+ if parsedURL.Scheme != expectedURL.Scheme ||
+ parsedURL.Host != expectedURL.Host ||
+ parsedURL.Path != expectedURL.Path {
+ v.log.Debug("URL doesn't match configured QR URL pattern",
+ "url", rawURL, "expected", v.config.Communication.QrUrl)
+ return "", false
+ }
+ }
+ }
+
+ if v.config.Communication.ApiSelfApproveMethod != "" {
+ if !strings.Contains(parsedURL.Path, v.config.Communication.ApiSelfApproveMethod) {
+ v.log.Debug("URL doesn't contain expected API method",
+ "url", parsedURL.Path, "expected", v.config.Communication.ApiSelfApproveMethod)
+ return "", false
+ }
+ }
+
+ token = parsedURL.Query().Get("token")
+ if token == "" {
+ v.log.Debug("URL missing token parameter", "url", rawURL)
+ return "", false
+ }
+
+ v.log.Debug("URL validation successful", "url", rawURL)
+ return token, true
+}
+
+func NewLinkValidator(config *config.Config, log *logger.Logger) LinkValidator {
+ return &linkValidatorImpl{
+ config: config,
+ log: log,
+ }
+}
diff --git a/src/internal/validator/validator.go b/src/internal/validator/validator.go
deleted file mode 100644
index e72b1ee..0000000
--- a/src/internal/validator/validator.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2025 Nikolai Papin
-//
-// This file is part of the Auto Attendance app that looks for
-// self-attend QR-codes during lectures and opens their URLs in your
-// browser.
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
-// the GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-package validator