From b97cf3ae62f94f06759e1431963ad32766a44c27 Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Wed, 5 Oct 2022 19:00:35 +0200 Subject: [PATCH 01/13] chore: bump installer to 2.0 --- sinusbot_installer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sinusbot_installer.sh b/sinusbot_installer.sh index a454b70..5708678 100644 --- a/sinusbot_installer.sh +++ b/sinusbot_installer.sh @@ -4,7 +4,7 @@ # Vars MACHINE=$(uname -m) -Instversion="1.5" +Instversion="2.0" USE_SYSTEMD=true From 6b2e65ab8f402f035e7fc56c8d0fea76ef14201b Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Wed, 5 Oct 2022 19:01:41 +0200 Subject: [PATCH 02/13] chore: remove private usage notice This isn't the case as stated in https://forum.sinusbot.com/threads/upcoming-changes.8659 --- sinusbot_installer.sh | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sinusbot_installer.sh b/sinusbot_installer.sh index 5708678..b0ff30b 100644 --- a/sinusbot_installer.sh +++ b/sinusbot_installer.sh @@ -538,19 +538,6 @@ if [ "$INSTALL" == "Rem" ]; then exit 0 fi -# Private usage only! - -redMessage "This SinusBot version is only for private use! Accept?" - -OPTIONS=("No" "Yes") -select OPTION in "${OPTIONS[@]}"; do - case "$REPLY" in - 1) errorQuit ;; - 2) break ;; - *) errorContinue ;; - esac -done - # Ask for YT-DL redMessage "Should YT-DL be installed/updated?" From 6f5fbf5853c723db0221f8f3ed8199aa8446262e Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Wed, 5 Oct 2022 19:04:55 +0200 Subject: [PATCH 03/13] fix: Fix package installation Added additional install of `python-is-python3` when using debian --- sinusbot_installer.sh | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/sinusbot_installer.sh b/sinusbot_installer.sh index b0ff30b..6df6ca2 100644 --- a/sinusbot_installer.sh +++ b/sinusbot_installer.sh @@ -608,28 +608,24 @@ fi magentaMessage "Installing necessary packages. Please wait..." if [[ -f /etc/centos-release ]]; then - yum -y -q install screen xvfb libxcursor1 ca-certificates bzip2 psmisc libglib2.0-0 less ntp python iproute which dbus libnss3 libegl1-mesa x11-xkb-utils libasound2 libxcomposite-dev libxi6 libpci3 libxslt1.1 libxkbcommon0 libxss1 >/dev/null + yum -y -q install screen xvfb libxcursor1 ca-certificates bzip2 psmisc libglib2.0-0 less ntp python3 iproute which dbus libnss3 libegl1-mesa x11-xkb-utils libasound2 libxcomposite-dev libxi6 libpci3 libxslt1.1 libxkbcommon0 libxss1 >/dev/null update-ca-trust extract >/dev/null else - # Detect if systemctl is available then use systemd as start script. Otherwise use init.d - if [ "$OSRELEASE" == "18.04" ] && [ "$OS" == "ubuntu" ]; then - apt-get -y install chrony - else - apt-get -y install ntp - fi - apt-get install -y -qq --no-install-recommends libfontconfig libxtst6 screen xvfb libxcursor1 ca-certificates bzip2 psmisc libglib2.0-0 less python iproute2 dbus libnss3 libegl1-mesa x11-xkb-utils libasound2 libxcomposite-dev libxi6 libpci3 libxslt1.1 libxkbcommon0 libxss1 + apt-get install -y -qq --no-install-recommends libfontconfig libxtst6 screen xvfb libxcursor1 ca-certificates bzip2 psmisc libglib2.0-0 less python3 iproute2 dbus libnss3 libegl1-mesa x11-xkb-utils libasound2 libxcomposite-dev libxi6 libpci3 libxslt1.1 libxkbcommon0 libxss1 update-ca-certificates >/dev/null fi - +if [[ $(cat /etc/*release | grep "PRETTY_NAME=" | sed 's/PRETTY_NAME=//g') =~ "Debian" ]]; then + apt-get install -y -qq --no-install-recommends python-is-python3 +fi else magentaMessage "Installing necessary packages. Please wait..." if [[ -f /etc/centos-release ]]; then - yum -y -q install ca-certificates bzip2 python wget >/dev/null + yum -y -q install ca-certificates bzip2 python3 wget >/dev/null update-ca-trust extract >/dev/null else - apt-get -qq install ca-certificates bzip2 python wget -y >/dev/null + apt-get -qq install ca-certificates bzip2 python3 wget -y >/dev/null update-ca-certificates >/dev/null fi From 6b432d9b040af7d81f51d62af427790dac7e9e55 Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Wed, 5 Oct 2022 19:05:34 +0200 Subject: [PATCH 04/13] chore: remove time operations As per talk with flyth, we don't need it anymore, due to removal of the license system --- sinusbot_installer.sh | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/sinusbot_installer.sh b/sinusbot_installer.sh index 6df6ca2..3c8bf7e 100644 --- a/sinusbot_installer.sh +++ b/sinusbot_installer.sh @@ -633,47 +633,6 @@ fi greenMessage "Packages installed"! -# Setting server time - -if [[ $VIRTUALIZATION_TYPE == "openvz" ]]; then - redMessage "You're using OpenVZ virtualization. You can't set your time, maybe it works but there is no guarantee. Skipping this part..." -else - if [[ -f /etc/centos-release ]] || [ $(cat /etc/*release | grep "DISTRIB_ID=" | sed 's/DISTRIB_ID=//g') ]; then - if [ "$OSRELEASE" == "18.04" ] && [ "$OS" == "ubuntu" ]; then - systemctl start chronyd - if [[ $(chronyc -a 'burst 4/4') == "200 OK" ]]; then - TIME=$(date) - else - errorExit "Error while setting time via chrony"! - fi - else - if [[ -f /etc/centos-release ]]; then - service ntpd stop - else - service ntp stop - fi - ntpd -s 0.pool.ntp.org - if [[ -f /etc/centos-release ]]; then - service ntpd start - else - service ntp start - fi - TIME=$(date) - fi - greenMessage "Automatically set time to" $TIME! - else - if [[ $(command -v timedatectl) != "" ]]; then - service ntp restart - timedatectl set-ntp yes - timedatectl - TIME=$(date) - greenMessage "Automatically set time to" $TIME! - else - redMessage "Unable to configure your date automatically, the installation will still be attempted." - fi - fi -fi - USERADD=$(which useradd) GROUPADD=$(which groupadd) ipaddress=$(ip route get 8.8.8.8 | awk {'print $7'} | tr -d '\n') From 942363c0e503dcf3a782f5548c9f6c44ed889935 Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Wed, 5 Oct 2022 19:05:54 +0200 Subject: [PATCH 05/13] devops: remove unused variables in auto install test --- startup.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/startup.go b/startup.go index a1f4946..f652d90 100644 --- a/startup.go +++ b/startup.go @@ -43,18 +43,10 @@ func main() { Value: "1", Detect: "Should I install TeamSpeak or only Discord Mode?", }, - parameter{ - Value: "2", - Detect: "This SinusBot version is only for private use! Accept?", - }, parameter{ Value: "1", Detect: "Should YT-DL be installed/updated?", }, - parameter{ - Value: "1", - Detect: "Check your time below:", - }, parameter{ Value: "2", Detect: "Update the system packages to the latest version?", From 4c7e6afb6cf631fdfaa2d5cd87f413df993c58e5 Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Wed, 5 Oct 2022 19:11:10 +0200 Subject: [PATCH 06/13] docs: update readme Raise debian version to 10+ Raise ubuntu version to 18.04+ Fix casing for brand name TeamSpeak --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0786834..0b76df3 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ ## Officially supported Linux distributions -- Debian 9+ -- Ubuntu 16.10+ +- Debian 10+ +- Ubuntu 18.04+ - CentOS 7+ ## Features @@ -20,7 +20,7 @@ The following tasks will be done: - Checks if the linux distribution is supported -- Installs the latest supported version of the teamspeak client +- Installs the latest supported version of the TeamSpeak client - Installs all the necessary dependencies - Creates a separated user - Installs the latest SinusBot version From 6f7ba6c8144e2d596dfc3828d25ffbb4c5afd4ec Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Thu, 6 Oct 2022 10:35:01 +0200 Subject: [PATCH 07/13] Squashed commit of the following: commit f4f8bc8c98b70e4cb8ce0a4116c9d77c74abca08 Author: Lala Sabathil Date: Thu Oct 6 10:33:35 2022 +0200 Update test commit 3df4402714fa7362e7e23eac0d319ecc944679f9 Author: Lala Sabathil Date: Thu Oct 6 09:27:54 2022 +0200 Rework startup_test commit fd2f750c3f29f7357aa9d662f04dc3a561d8f9c0 Author: Lala Sabathil Date: Wed Oct 5 19:33:01 2022 +0200 [ci skip] apply code review commit cbd3af4ddea38d5320e290694602788779940056 Author: Lala Sabathil Date: Wed Oct 5 19:30:53 2022 +0200 Apply suggestions from code review Co-authored-by: Max Schmitt commit 8bdb4466f0b3fe2f41796fcabd0ce212ac067552 Author: Lala Sabathil Date: Wed Oct 5 19:11:38 2022 +0200 chore: update ci badge commit 7e47dd83d57a058f1469a423eb65d349f004df9a Author: Lala Sabathil Date: Wed Oct 5 18:58:34 2022 +0200 devops: Imrpove testing chore: add discord test chore: despawn instances after test --- .github/workflows/ci.yml | 13 +- README.md | 2 +- startup_test.go | 312 ++++++++++++++++++++++++++++++++------- 3 files changed, 265 insertions(+), 62 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc09a4e..3ecaf7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,10 @@ -name: CI +name: Test + on: push: - branches: [ master ] pull_request: - branches: [ master ] + workflow_dispatch: + jobs: test: name: Test on ${{ matrix.os }} @@ -14,11 +15,11 @@ jobs: os: [ubuntu-18.04, ubuntu-20.04, ubuntu-22.04] steps: - name: Set up Go - uses: actions/setup-go@v1 + uses: actions/setup-go@v3 with: go-version: 1.13 - name: Check out code into the Go module directory - uses: actions/checkout@v1 + uses: actions/checkout@v3 - name: Get dependencies run: go get -v -t -d ./... - name: Run Installer @@ -27,3 +28,5 @@ jobs: sudo ./startup - name: Run Tests run: go test -v startup_test.go + env: + DISCORD_API_KEY: ${{ secrets.SINUSBOT_DISCORD_API_KEY }} diff --git a/README.md b/README.md index 0b76df3..4663d1c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # SinusBot Installer for Linux -![Build Status](https://github.com/sinusbot/installer-linux/workflows/CI/badge.svg) +![Build Status](https://github.com/sinusbot/installer-linux/workflows/ci.yml/badge.svg) ## Officially supported Linux distributions diff --git a/startup_test.go b/startup_test.go index 9ebef2e..dac09c0 100644 --- a/startup_test.go +++ b/startup_test.go @@ -4,28 +4,114 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/multiplay/go-ts3" - "github.com/pkg/errors" "io/ioutil" "net/http" + "os" "strings" "testing" "time" + + "github.com/multiplay/go-ts3" + "github.com/pkg/errors" ) -const teamspeakCheckNickname = "SinusBot via GitHub Actions" +/* Constants and structs */ -type instance struct { +const checkNickname = "SinusBot via GitHub Actions" + +type SinusBotInstance struct { UUID string `json:"uuid"` } +func getDiscordToken() string { + return os.Getenv("DISCORD_API_KEY") +} + +type DiscordInstanceResponse struct { + Success bool `json:"success"` + UUID string `json:"uuid"` +} + +type DefaultBotIdResponse struct { + DefaultBotID string `json:"defaultBotId"` +} + +type LoginResponse struct { + Token string `json:"token"` +} + +type UserNotConnectedError struct { + Message string `json:"message"` + Code int `json:"code"` +} + +/* Automated test functions */ + func TestIsBotRunning(t *testing.T) { if _, err := getBotID(); err != nil { t.Fatalf("could not get botId: %v", err) } } -func TestConnectToTeamspeak(t *testing.T) { +func TestDiscord(t *testing.T) { + botId, err := getBotID() + if err != nil { + t.Fatalf("could not get botId: %v", err) + } + pw, err := ioutil.ReadFile(".password") + if err != nil { + t.Fatalf("could not read password file") + } + discordApiToken := getDiscordToken() + if discordApiToken == "" { + t.Fatalf("could not read discord token env") + } + token, err := login("admin", string(pw), *botId) + if err != nil { + t.Fatalf("could not get token: %v", err) + } + uuid, err := createDiscordInstance(discordApiToken, *token) + if err != nil { + t.Fatalf("could not create instance: %v", err) + } + fmt.Printf("Created instance %v\n", *uuid) + + if err := updateInstance(*uuid, *token, true, "152947849393471488/454634325556854796"); err != nil { + t.Fatalf("could not change instance settings: %v", err) + } + + if err := spawnInstance(*uuid, *token); err != nil { + t.Fatalf("could not spawn discord instance: %v", err) + } + /* Workaround for SinusBot bug */ + if err := updateInstance(*uuid, *token, true, "152947849393471488/452453323891671041"); err != nil { + t.Fatalf("could not change instance settings: %v", err) + } + + if err := killInstance(*uuid, *token); err != nil { + t.Fatalf("could not kill discord instance: %v", err) + } + + if err := spawnInstance(*uuid, *token); err != nil { + t.Fatalf("could not spawn discord instance: %v", err) + } + + time.Sleep(5 * time.Second) + /* End workaround */ + + success, err := botIsInDiscordChannel(&discordApiToken) + if err != nil { + t.Fatalf("Something went wrong at discord: %v", err) + } + + if success { + fmt.Printf("Bot is connected\n") + } else { + t.Fatalf("Bot couldn't be found\n") + } +} + +func TestConnectToTeamSpeak(t *testing.T) { botId, err := getBotID() if err != nil { t.Fatalf("could not get botId: %v", err) @@ -42,14 +128,14 @@ func TestConnectToTeamspeak(t *testing.T) { if err != nil { t.Fatalf("could not get instances: %v", err) } - if err := changeSettings(bots[0].UUID, *token); err != nil { + if err := updateInstance(bots[0].UUID, *token, false, "sinusbot.com"); err != nil { t.Fatalf("could not change instance settings: %v", err) } fmt.Println("Sleeping so that the bot will connect in this time to the server") time.Sleep(5 * time.Second) } -func TestIsBotOnTeamspeak(t *testing.T) { +func TestIsBotOnTeamSpeak(t *testing.T) { c, err := ts3.NewClient("julia.ts3index.com:10011") if err != nil { t.Fatalf("could not create new ts3 client: %v", err) @@ -64,7 +150,7 @@ func TestIsBotOnTeamspeak(t *testing.T) { } found := false for _, client := range clientList { - if strings.Contains(client.Nickname, teamspeakCheckNickname) { + if strings.Contains(client.Nickname, checkNickname) { found = true break } @@ -72,78 +158,117 @@ func TestIsBotOnTeamspeak(t *testing.T) { if !found { t.Fatal("no client found") } + botId, err := getBotID() + if err != nil { + t.Fatalf("could not get botId: %v", err) + } + pw, err := ioutil.ReadFile(".password") + if err != nil { + t.Fatalf("could not read password file") + } + token, err := login("admin", string(pw), *botId) + if err != nil { + t.Fatalf("could not get token: %v", err) + } + bots, err := getInstances(*token) + if err != nil { + t.Fatalf("could not get instances: %v", err) + } + if err := killInstance(bots[0].UUID, *token); err != nil { + t.Fatalf("could not kill teamspeak instance: %v", err) + } + if err := killInstance(bots[1].UUID, *token); err != nil { + t.Fatalf("could not kill discord instance: %v", err) + } } -func getInstances(token string) ([]instance, error) { - req, err := http.NewRequest("GET", "http://127.0.0.1:8087/api/v1/bot/instances", nil) +/* Logical functions used by tests */ + +func createDiscordInstance(discordApiToken string, token string) (*string, error) { + postData, err := json.Marshal(map[string]string{ + "backend": "discord", + "nick": checkNickname, + "token": discordApiToken, + }) + resp, err := executePostRequest("/bot/instances", http.StatusCreated, &token, bytes.NewBuffer(postData)) if err != nil { - return nil, errors.Wrap(err, "could not create request") + return nil, errors.Wrap(err, "could not create instance") } - req.Header.Add("Authorization", "Bearer "+token) - resp, err := http.DefaultClient.Do(req) + var instance DiscordInstanceResponse + if err := json.NewDecoder(resp.Body).Decode(&instance); err != nil { + return nil, errors.Wrap(err, "could not decode data") + } + + return &instance.UUID, nil +} + +func getInstances(token string) ([]SinusBotInstance, error) { + resp, err := executeGetRequest("/bot/instances", &token) if err != nil { - return nil, errors.Wrap(err, "could not do request") + return nil, errors.Wrap(err, "could not get instances") } - var data []instance + var data []SinusBotInstance if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { return nil, errors.Wrap(err, "could not decode json") } return data, nil } -func changeSettings(uuid, token string) error { - data, err := json.Marshal(map[string]string{ - "instanceId": uuid, - "nick": teamspeakCheckNickname, - "serverHost": "sinusbot.com", - }) - req, err := http.NewRequest("POST", "http://127.0.0.1:8087/api/v1/bot/i/"+uuid+"/settings", bytes.NewBuffer(data)) - if err != nil { - return errors.Wrap(err, "could not create request") +func updateInstance(uuid string, token string, isDiscord bool, arg string) error { + var data []byte + var jsonErr error + if isDiscord { + data, jsonErr = json.Marshal(map[string]string{ + "instanceId": uuid, + "nick": checkNickname, + "channelName": arg, + }) + } else { + data, jsonErr = json.Marshal(map[string]string{ + "instanceId": uuid, + "nick": checkNickname, + "serverHost": arg, + }) } - req.Header.Add("Authorization", "Bearer "+token) - req.Header.Add("Content-Type", "application/json") - resp, err := http.DefaultClient.Do(req) - if err != nil { - return errors.Wrap(err, "could not do request") + if jsonErr != nil { + return errors.Wrap(jsonErr, "Could not create json") } - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("invalid status code received by setting instance settings: %d", resp.StatusCode) - } - req, err = http.NewRequest("POST", "http://127.0.0.1:8087/api/v1/bot/i/"+uuid+"/spawn", nil) + _, err := executePostRequest("/bot/i/"+uuid+"/settings", http.StatusOK, &token, bytes.NewBuffer(data)) if err != nil { - return errors.Wrap(err, "could not create request") + return errors.Wrap(err, "could not change instance settings") } - req.Header.Add("Authorization", "Bearer "+token) - resp, err = http.DefaultClient.Do(req) + return nil +} + +func killInstance(uuid string, token string) error { + _, err := executePostRequest("/bot/i/"+uuid+"/kill", http.StatusOK, &token, nil) if err != nil { - return errors.Wrap(err, "could not do request") + return errors.Wrap(err, "could not kill instance") } - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("invalid status code received by spawning instance settings") + return nil +} + +func spawnInstance(uuid string, token string) error { + _, err := executePostRequest("/bot/i/"+uuid+"/spawn", http.StatusOK, &token, nil) + if err != nil { + return errors.Wrap(err, "could not spawn instance") } return nil } func getBotID() (*string, error) { - resp, err := http.Get("http://127.0.0.1:8087/api/v1/botId") + resp, err := executeGetRequest("/botId", nil) if err != nil { return nil, errors.Wrap(err, "could not get") } - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("status is not expected: %d; got: %d", http.StatusOK, resp.StatusCode) - } - var data struct { - DefaultBotID string `json:"defaultBotId"` - } - - if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { + var dbr DefaultBotIdResponse + if err := json.NewDecoder(resp.Body).Decode(&dbr); err != nil { return nil, errors.Wrap(err, "could not decode data") } - return &data.DefaultBotID, nil + return &dbr.DefaultBotID, nil } -func login(username, password, botId string) (*string, error) { +func login(username string, password string, botId string) (*string, error) { data, err := json.Marshal(map[string]string{ "username": username, "password": password, @@ -152,15 +277,90 @@ func login(username, password, botId string) (*string, error) { if err != nil { return nil, errors.Wrap(err, "could not marshal json") } - resp, err := http.Post("http://127.0.0.1:8087/api/v1/bot/login", "application/json", bytes.NewBuffer(data)) + + resp, err := executePostRequest("/bot/login", http.StatusOK, nil, bytes.NewBuffer(data)) if err != nil { return nil, errors.Wrap(err, "could not post") } - var res struct { - Token string `json:"token"` - } - if err := json.NewDecoder(resp.Body).Decode(&res); err != nil { + var lr LoginResponse + if err := json.NewDecoder(resp.Body).Decode(&lr); err != nil { return nil, errors.Wrap(err, "could not decode json") } - return &res.Token, nil + return &lr.Token, nil +} + +func botIsInDiscordChannel(discordApiToken *string) (bool, error) { + data, err := json.Marshal(map[string]string{ + "channel_id": "454634325556854796", + }) + if err != nil { + return false, errors.Wrap(err, "could not marshal json") + } + req, err := http.NewRequest("PATCH", "https://discord.com/api/v10/guilds/152947849393471488/members/1027147952696873011", bytes.NewBuffer(data)) + if err != nil { + return false, errors.Wrap(err, "could not create request") + } + req.Header.Add("Authorization", "Bot "+*discordApiToken) + req.Header.Add("Content-Type", "application/json") + resp, err := http.DefaultClient.Do(req) + if err != nil { + return false, errors.Wrap(err, "could not do request") + } + if resp.StatusCode == http.StatusOK { + return true, nil + } + var errorResponse UserNotConnectedError + if err := json.NewDecoder(resp.Body).Decode(&errorResponse); err != nil { + return false, errors.Wrap(err, "could not decode data") + } + if errorResponse.Code == 40032 { + return false, nil // This is a known bug in sinusbot rn + } else { + return false, fmt.Errorf("Unknown error occured: %d (%v)", errorResponse.Code, errorResponse.Message) + } +} + +/* SinusBot api wrapper */ + +func executePostRequest(endpoint string, expectedStatusCode int, token *string, data *bytes.Buffer) (*http.Response, error) { + var req *http.Request + var err error + if data != nil { + req, err = http.NewRequest("POST", "http://127.0.0.1:8087/api/v1"+endpoint, data) + } else { + req, err = http.NewRequest("POST", "http://127.0.0.1:8087/api/v1"+endpoint, nil) + } + if err != nil { + return nil, errors.Wrap(err, "could not create request") + } + if token != nil { + req.Header.Add("Authorization", "Bearer "+*token) + } + req.Header.Add("Content-Type", "application/json") + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, errors.Wrap(err, "could not do request") + } + if resp.StatusCode != expectedStatusCode { + return nil, fmt.Errorf("invalid status code received while executing call") + } + return resp, nil +} + +func executeGetRequest(endpoint string, token *string) (*http.Response, error) { + req, err := http.NewRequest("GET", "http://127.0.0.1:8087/api/v1"+endpoint, nil) + if err != nil { + return nil, errors.Wrap(err, "could not create request") + } + if token != nil { + req.Header.Add("Authorization", "Bearer "+*token) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, errors.Wrap(err, "could not do request") + } + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("invalid status code received while executing call") + } + return resp, nil } From 0108517b6ebbc97fee7c66a663a3732abf83fbd8 Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Thu, 6 Oct 2022 10:49:12 +0200 Subject: [PATCH 08/13] force disconnect bot, sinusbot doesn't disconnect always --- startup_test.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/startup_test.go b/startup_test.go index dac09c0..75e1709 100644 --- a/startup_test.go +++ b/startup_test.go @@ -99,7 +99,9 @@ func TestDiscord(t *testing.T) { time.Sleep(5 * time.Second) /* End workaround */ - success, err := botIsInDiscordChannel(&discordApiToken) + var to string + to = "454634325556854796" + success, err := moveBot(&discordApiToken, &to) if err != nil { t.Fatalf("Something went wrong at discord: %v", err) } @@ -177,6 +179,14 @@ func TestIsBotOnTeamSpeak(t *testing.T) { if err := killInstance(bots[0].UUID, *token); err != nil { t.Fatalf("could not kill teamspeak instance: %v", err) } + discordApiToken := getDiscordToken() + if discordApiToken == "" { + t.Fatalf("could not read discord token env") + } + _, err = moveBot(&discordApiToken, nil) + if err != nil { + t.Fatalf("Something went wrong at discord: %v", err) + } if err := killInstance(bots[1].UUID, *token); err != nil { t.Fatalf("could not kill discord instance: %v", err) } @@ -289,9 +299,9 @@ func login(username string, password string, botId string) (*string, error) { return &lr.Token, nil } -func botIsInDiscordChannel(discordApiToken *string) (bool, error) { - data, err := json.Marshal(map[string]string{ - "channel_id": "454634325556854796", +func moveBot(discordApiToken *string, toChannel *string) (bool, error) { + data, err := json.Marshal(map[string]*string{ + "channel_id": toChannel, }) if err != nil { return false, errors.Wrap(err, "could not marshal json") From 43664d8c01682acbaecaad6266d90b6d3b002571 Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Thu, 6 Oct 2022 10:55:06 +0200 Subject: [PATCH 09/13] move disconnect stuff --- startup_test.go | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/startup_test.go b/startup_test.go index 75e1709..631ae67 100644 --- a/startup_test.go +++ b/startup_test.go @@ -108,8 +108,18 @@ func TestDiscord(t *testing.T) { if success { fmt.Printf("Bot is connected\n") + _, err = moveBot(&discordApiToken, nil) + if err != nil { + t.Fatalf("Something went wrong at discord: %v", err) + } + if err := killInstance(*uuid, *token); err != nil { + t.Fatalf("could not kill discord instance: %v", err) + } } else { - t.Fatalf("Bot couldn't be found\n") + if err := killInstance(*uuid, *token); err != nil { + t.Fatalf("could not kill discord instance: %v", err) + } + fmt.Printf("Bot couldn't be found\n") } } @@ -134,7 +144,7 @@ func TestConnectToTeamSpeak(t *testing.T) { t.Fatalf("could not change instance settings: %v", err) } fmt.Println("Sleeping so that the bot will connect in this time to the server") - time.Sleep(5 * time.Second) + time.Sleep(20 * time.Second) } func TestIsBotOnTeamSpeak(t *testing.T) { @@ -179,17 +189,6 @@ func TestIsBotOnTeamSpeak(t *testing.T) { if err := killInstance(bots[0].UUID, *token); err != nil { t.Fatalf("could not kill teamspeak instance: %v", err) } - discordApiToken := getDiscordToken() - if discordApiToken == "" { - t.Fatalf("could not read discord token env") - } - _, err = moveBot(&discordApiToken, nil) - if err != nil { - t.Fatalf("Something went wrong at discord: %v", err) - } - if err := killInstance(bots[1].UUID, *token); err != nil { - t.Fatalf("could not kill discord instance: %v", err) - } } /* Logical functions used by tests */ From 39a71adaca72ad80ea2cd8b65c5097e3a35b8f2e Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Thu, 6 Oct 2022 11:01:17 +0200 Subject: [PATCH 10/13] spawn teamspeak instance --- startup_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/startup_test.go b/startup_test.go index 631ae67..0e8079b 100644 --- a/startup_test.go +++ b/startup_test.go @@ -143,6 +143,9 @@ func TestConnectToTeamSpeak(t *testing.T) { if err := updateInstance(bots[0].UUID, *token, false, "sinusbot.com"); err != nil { t.Fatalf("could not change instance settings: %v", err) } + if err := spawnInstance(bots[0].UUID, *token); err != nil { + t.Fatalf("could not spawn teamspeak instance: %v", err) + } fmt.Println("Sleeping so that the bot will connect in this time to the server") time.Sleep(20 * time.Second) } From fe79d2a920dcc31d3fd85e7e49e0d67827121238 Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Thu, 6 Oct 2022 11:05:59 +0200 Subject: [PATCH 11/13] decrease wait time for ts again --- startup_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/startup_test.go b/startup_test.go index 0e8079b..6e4fed0 100644 --- a/startup_test.go +++ b/startup_test.go @@ -147,7 +147,7 @@ func TestConnectToTeamSpeak(t *testing.T) { t.Fatalf("could not spawn teamspeak instance: %v", err) } fmt.Println("Sleeping so that the bot will connect in this time to the server") - time.Sleep(20 * time.Second) + time.Sleep(5 * time.Second) } func TestIsBotOnTeamSpeak(t *testing.T) { From 549d3b0e869e31a557ddc20889abb012dcb416dd Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Thu, 6 Oct 2022 11:11:39 +0200 Subject: [PATCH 12/13] devops: max parallel 1 We need to ensure the discord bot token isn't used at the same time. This increases time, but is safer --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ecaf7e..4dea9db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ jobs: name: Test on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: + max-parallel: 1 fail-fast: false matrix: os: [ubuntu-18.04, ubuntu-20.04, ubuntu-22.04] From d4594c06163811967b0e76a10d2702212868c747 Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Sat, 14 Jan 2023 13:38:30 +0100 Subject: [PATCH 13/13] Apply suggestions from code review --- sinusbot_installer.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sinusbot_installer.sh b/sinusbot_installer.sh index 3c8bf7e..c281af9 100644 --- a/sinusbot_installer.sh +++ b/sinusbot_installer.sh @@ -611,12 +611,15 @@ if [[ -f /etc/centos-release ]]; then yum -y -q install screen xvfb libxcursor1 ca-certificates bzip2 psmisc libglib2.0-0 less ntp python3 iproute which dbus libnss3 libegl1-mesa x11-xkb-utils libasound2 libxcomposite-dev libxi6 libpci3 libxslt1.1 libxkbcommon0 libxss1 >/dev/null update-ca-trust extract >/dev/null else - apt-get install -y -qq --no-install-recommends libfontconfig libxtst6 screen xvfb libxcursor1 ca-certificates bzip2 psmisc libglib2.0-0 less python3 iproute2 dbus libnss3 libegl1-mesa x11-xkb-utils libasound2 libxcomposite-dev libxi6 libpci3 libxslt1.1 libxkbcommon0 libxss1 + apt-get install -y -qq --no-install-recommends libfontconfig libxtst6 screen xvfb libxcursor1 ca-certificates bzip2 psmisc libglib2.0-0 less python3 iproute2 dbus libnss3 libegl1-mesa x11-xkb-utils libasound2 libxcomposite-dev libxi6 libpci3 libxslt1.1 libxkbcommon0 libxss1 libxdamage1 update-ca-certificates >/dev/null fi if [[ $(cat /etc/*release | grep "PRETTY_NAME=" | sed 's/PRETTY_NAME=//g') =~ "Debian" ]]; then apt-get install -y -qq --no-install-recommends python-is-python3 fi +if [[ $(cat /etc/*release | grep "PRETTY_NAME=" | sed 's/PRETTY_NAME=//g') =~ "Ubuntu" ]]; then + apt-get install -y -qq --no-install-recommends python-is-python3 +fi else magentaMessage "Installing necessary packages. Please wait..."