diff --git a/.forgejo/workflows/bake.yml b/.forgejo/workflows/bake.yml deleted file mode 100644 index a28de2b..0000000 --- a/.forgejo/workflows/bake.yml +++ /dev/null @@ -1,54 +0,0 @@ -on: - push: - branches: - - 'main' - tags: - - 'v*' - paths: - - '**.go' - - '**.html' - - 'Dockerfile' - - 'Dockerfile.*' - - 'docker-bake.hcl' - workflow_dispatch: - -jobs: - bake: - runs-on: docker - steps: - - name: Prepare Registry FQDN - id: registry - run: | - registry=${{ github.server_url }} - registry=${registry##http*://} - echo "registry=${registry}" >> "$GITHUB_OUTPUT" - - - name: Login to Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ steps.registry.outputs.registry }} - username: ${{ github.repository_owner }} - password: ${{ secrets.TOKEN }} - - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - tags: | - type=ref,event=branch - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - - - name: Build and push - uses: docker/bake-action@v6 - with: - source: . - env: - TAG: ${{ steps.meta.outputs.tags }} diff --git a/cmd/tweeter/webhook.go b/cmd/tweeter/webhook.go index 7995371..0c69601 100644 --- a/cmd/tweeter/webhook.go +++ b/cmd/tweeter/webhook.go @@ -3,7 +3,6 @@ package tweeter import ( "bytes" "encoding/json" - "html" "log" "net/http" "strings" @@ -81,7 +80,7 @@ func (app App) SendToWebhook(tweets []*ts.Tweet) { tweetText = strings.ReplaceAll(tweetText, video.URL, "") } - mainEmbed.SetText(html.UnescapeString(strings.TrimSpace(tweetText))) + mainEmbed.SetText(strings.TrimSpace(tweetText)) for _, data := range webhooksToSend { err := sendRequest(app.config.Webhook, data) diff --git a/config.example.toml b/config.example.toml index fdcd679..b4da53d 100644 --- a/config.example.toml +++ b/config.example.toml @@ -1,19 +1,12 @@ username = "" password = "asd123" #proxyaddr = "socks5://localhost:5555" - -#usewebserver = false -indextarget = "https://discord.gg/Kw4MFGxYEj" # Optional -hostURL = "https://my.domain.tld" # Can be omitted if not using webserver - -webhook = "https://domain.tld/api/webhooks/" - +hostURL = "https://my.domain.tld" channels = [ "NinEverything", "NintendoEurope", "NintendoAmerica", ] - # Binary representation for efficient filtering # Bit from left to right (most to least significant bit): IsSelfThread, IsRetweet, IsReply, IsPin, IsQuoted filter = [ diff --git a/docker-bake.hcl b/docker-bake.hcl index 7cb61be..e18ac8c 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -8,8 +8,8 @@ variable "TAG" { function "generate_tags" { params = [images, versions] result = distinct(flatten( - [for i in split(",", replace(images, "\n", ",")) : - [for v in split(",", replace(versions, "\n", ",")) : + [for i in split(",", images) : + [for v in split(",", versions) : "${i}:${v}" ] ])) @@ -24,8 +24,8 @@ target "default" { } target "prod" { inherits = ["default"] - platforms = ["linux/amd64", "linux/arm64", "linux/arm/v7", "linux/riscv64"] - #platforms = ["linux/amd64", "linux/arm64"] + //platforms = ["linux/amd64", "linux/arm64", "linux/arm/v7", "linux/riscv64"] + platforms = ["linux/amd64", "linux/arm64"] dockerfile = "Dockerfile.multiarch" output = ["type=registry"] attest = [ diff --git a/nix/default.nix b/nix/default.nix deleted file mode 100644 index b07d863..0000000 --- a/nix/default.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ pkgs ? ( - let - inherit (builtins) fetchTree fromJSON readFile; - inherit ((fromJSON (readFile ./flake.lock)).nodes) nixpkgs gomod2nix; - in - import (fetchTree nixpkgs.locked) { - overlays = [ - (import "${fetchTree gomod2nix.locked}/overlay.nix") - ]; - } -) -, buildGoApplication ? pkgs.buildGoApplication -}: - -buildGoApplication { - pname = "discord-tweeter"; - version = "0.1"; - pwd = ./.; - src = ../.; - modules = ./gomod2nix.toml; -} diff --git a/nix/flake.lock b/nix/flake.lock deleted file mode 100644 index a0e83ed..0000000 --- a/nix/flake.lock +++ /dev/null @@ -1,85 +0,0 @@ -{ - "nodes": { - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "gomod2nix": { - "inputs": { - "flake-utils": [ - "flake-utils" - ], - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1742209644, - "narHash": "sha256-jMy1XqXqD0/tJprEbUmKilTkvbDY/C0ZGSsJJH4TNCE=", - "owner": "nix-community", - "repo": "gomod2nix", - "rev": "8f3534eb8f6c5c3fce799376dc3b91bae6b11884", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "gomod2nix", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1742288794, - "narHash": "sha256-Txwa5uO+qpQXrNG4eumPSD+hHzzYi/CdaM80M9XRLCo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "b6eaf97c6960d97350c584de1b6dcff03c9daf42", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "gomod2nix": "gomod2nix", - "nixpkgs": "nixpkgs" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/nix/flake.nix b/nix/flake.nix deleted file mode 100644 index 80ad039..0000000 --- a/nix/flake.nix +++ /dev/null @@ -1,24 +0,0 @@ -{ - description = "NixOS flake for discord-tweeter"; - - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - inputs.flake-utils.url = "github:numtide/flake-utils"; - inputs.gomod2nix.url = "github:nix-community/gomod2nix"; - inputs.gomod2nix.inputs.nixpkgs.follows = "nixpkgs"; - inputs.gomod2nix.inputs.flake-utils.follows = "flake-utils"; - - outputs = { self, nixpkgs, flake-utils, gomod2nix }: - (flake-utils.lib.eachDefaultSystem - (system: - let - pkgs = nixpkgs.legacyPackages.${system}; - - callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage; - in - { - nixosModules.default = callPackage ./services.nix { inherit self; }; - packages.default = callPackage ./. { inherit (gomod2nix.legacyPackages.${system}) buildGoApplication; }; - devShells.default = callPackage ./shell.nix { inherit (gomod2nix.legacyPackages.${system}) mkGoEnv gomod2nix; }; - }) - ); -} diff --git a/nix/gomod2nix.toml b/nix/gomod2nix.toml deleted file mode 100644 index 5edd8c3..0000000 --- a/nix/gomod2nix.toml +++ /dev/null @@ -1,21 +0,0 @@ -schema = 3 - -[mod] - [mod."github.com/AlexEidt/Vidio"] - version = "v1.5.1" - hash = "sha256-WdnCYjxbFqDmh/IVaVCCc1TzvklKdJtDMdIgn6m6NTM=" - [mod."github.com/BurntSushi/toml"] - version = "v1.5.0" - hash = "sha256-wX8bEVo7swuuAlm0awTIiV1KNCAXnm7Epzwl+wzyqhw=" - [mod."github.com/imperatrona/twitter-scraper"] - version = "v0.0.16" - hash = "sha256-nbv9fI6/3OxnC8NaLO82UfcwbJMz1jxvfNjZPOrILzM=" - [mod."github.com/jmoiron/sqlx"] - version = "v1.4.0" - hash = "sha256-0H132+A983nBr2zEyCKsJoBCZlC9pG+ylEcGysxKL4M=" - [mod."github.com/mattn/go-sqlite3"] - version = "v1.14.24" - hash = "sha256-taGKFZFQlR5++5b2oZ1dYS3RERKv6yh1gniNWhb4egg=" - [mod."golang.org/x/net"] - version = "v0.37.0" - hash = "sha256-sZKbJISVdBwyuYRQgrraTKxeIORWlzK5hScceQ2dE58=" diff --git a/nix/services.nix b/nix/services.nix deleted file mode 100644 index 6658611..0000000 --- a/nix/services.nix +++ /dev/null @@ -1,51 +0,0 @@ -{config, lib, pkgs, ...}: - -with lib; - -let - cfg = config.services.discord-tweeter; - - format = pkgs.formats.toml { }; - configFile = format.generate "config.toml" cfg.settings; -in -{ - options.services.discord-tweeter = { - enable = mkEnableOption (lib.mdDoc "discord-tweeter"); - - settings = mkOption { - type = format.type; - default = { - username = ""; - password = ""; - proxyaddr = ""; - webhook = ""; - DbPath = "/var/lib/discord-tweeter/"; - CookiePath = "/var/lib/discord-tweeter/"; - channels = [ ]; - filter = [ 0b11111 ]; - UseWebServer = true; - HostURL = ""; - WebPort = 8080; - UserAgents = [ "discordbot" "curl" "httpie" "lwp-request" "wget" "python-requests" "openbsd ftp" "powershell" ]; - NitterBase = "https://xcancel.com"; - }; - description = lib.mdDoc '' - ''; - }; - }; - - config = mkIf cfg.enable { - systemd.services.discord-tweeter = { - description = "Send tweets to Discord by scraping Twitter (now X)"; - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - DynamicUser = true; - ExecStart = "${self.packages.${pkgs.system}.default}/bin/discord-tweeter ${configFile}"; - Restart = "on-failure"; - }; - }; - }; -} - diff --git a/nix/shell.nix b/nix/shell.nix deleted file mode 100644 index 8d806a2..0000000 --- a/nix/shell.nix +++ /dev/null @@ -1,24 +0,0 @@ -{ pkgs ? ( - let - inherit (builtins) fetchTree fromJSON readFile; - inherit ((fromJSON (readFile ./flake.lock)).nodes) nixpkgs gomod2nix; - in - import (fetchTree nixpkgs.locked) { - overlays = [ - (import "${fetchTree gomod2nix.locked}/overlay.nix") - ]; - } - ) -, mkGoEnv ? pkgs.mkGoEnv -, gomod2nix ? pkgs.gomod2nix -}: - -let - goEnv = mkGoEnv { pwd = ../.; }; -in -pkgs.mkShell { - packages = [ - goEnv - gomod2nix - ]; -} diff --git a/pkg/config/config.go b/pkg/config/config.go index 499badb..dd540fb 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -20,7 +20,6 @@ type Config struct { WebPort uint16 UserAgents []string NitterBase string - IndexTarget string } func ConfigFromFile(filePath string) (*Config, error) { diff --git a/pkg/web/templates/tweet.html b/pkg/web/templates/tweet.html index 96165d5..d019a1b 100644 --- a/pkg/web/templates/tweet.html +++ b/pkg/web/templates/tweet.html @@ -5,8 +5,8 @@ - - + + {{- range $idx, $e := .Images }} diff --git a/pkg/web/templates/video.html b/pkg/web/templates/video.html index 2c02e15..c4dc13b 100644 --- a/pkg/web/templates/video.html +++ b/pkg/web/templates/video.html @@ -6,8 +6,8 @@ {{- if .Videos }} - - + + {{- range $idx, $e := .Videos }} diff --git a/pkg/web/web.go b/pkg/web/web.go index a8b5a5a..161bcc0 100644 --- a/pkg/web/web.go +++ b/pkg/web/web.go @@ -23,7 +23,7 @@ const ( //go:embed templates/*.html var templateFiles embed.FS -type Response struct { +type Reponse struct { StatusCode int ContentType string Content string @@ -34,7 +34,7 @@ type WebServer struct { scraper *ts.Scraper templates *template.Template avatarCache *cache.Cache[string, string] - responseCache *cache.Cache[string, Response] + responseCache *cache.Cache[string, Reponse] Server *http.Server } @@ -64,7 +64,7 @@ func New(config *config.Config, scraper *ts.Scraper) (*WebServer, error) { scraper, tmpl, cache.New[string, string](), - cache.New[string, Response](), + cache.New[string, Reponse](), &http.Server{ Handler: sm, Addr: fmt.Sprintf(":%d", config.WebPort), @@ -72,19 +72,12 @@ func New(config *config.Config, scraper *ts.Scraper) (*WebServer, error) { WriteTimeout: 30 * time.Second, }, } - sm.HandleFunc("GET /", ws.handleIndex) sm.HandleFunc("GET /avatar/{username}", ws.handleAvatar) sm.HandleFunc("GET /tweet/{id}", ws.handleTweet) sm.HandleFunc("GET /video/{id}", ws.handleVideo) return ws, nil } -func (ws WebServer) handleIndex(w http.ResponseWriter, r *http.Request) { - if ws.config.IndexTarget != "" { - http.Redirect(w, r, ws.config.IndexTarget, http.StatusPermanentRedirect) - } -} - func (ws WebServer) handleAvatar(w http.ResponseWriter, r *http.Request) { username := r.PathValue("username") @@ -137,7 +130,7 @@ func (ws WebServer) handleTemplate(w http.ResponseWriter, r *http.Request, id st } if !slices.Contains(ws.config.Channels, tweet.Username) { - res := Response{http.StatusBadRequest, "text/plain", "Bad Request"} + res := Reponse{http.StatusBadRequest, "text/plain", "Bad Request"} ws.responseCache.Set(template+"-"+id, res, TweetCacheTime) response(w, res) return @@ -189,7 +182,7 @@ func (ws WebServer) handleTemplate(w http.ResponseWriter, r *http.Request, id st return } - res := Response{http.StatusOK, "text/html", tpl.String()} + res := Reponse{http.StatusOK, "text/html", tpl.String()} ws.responseCache.Set(template+"-"+id, res, TweetCacheTime) response(w, res) } @@ -204,14 +197,14 @@ func validUserAgent(ua string, uas []string) bool { } func badRequest(w http.ResponseWriter) { - response(w, Response{http.StatusBadRequest, "text/plain", "Bad Request"}) + response(w, Reponse{http.StatusBadRequest, "text/plain", "Bad Request"}) } func serverError(w http.ResponseWriter) { - response(w, Response{http.StatusInternalServerError, "text/plain", "Internal Server Error"}) + response(w, Reponse{http.StatusInternalServerError, "text/plain", "Internal Server Error"}) } -func response(w http.ResponseWriter, res Response) { +func response(w http.ResponseWriter, res Reponse) { w.WriteHeader(res.StatusCode) w.Header().Set("Content-Type", res.ContentType) fmt.Fprint(w, res.Content)