Compare commits
No commits in common. "rewrite" and "master" have entirely different histories.
19
cmd/main.go
19
cmd/main.go
@ -1,19 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/mattburchett/go_telegram/pkg/core/config"
|
|
||||||
"github.com/mattburchett/go_telegram/pkg/service/telegram"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
conf, err := config.GetConfig("config.json")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to read JSON.")
|
|
||||||
}
|
|
||||||
|
|
||||||
tgBot := telegram.Bot{}
|
|
||||||
tgBot.Config = conf
|
|
||||||
tgBot.New(conf.Telegram.Token)
|
|
||||||
}
|
|
17
go.mod
17
go.mod
@ -1,17 +0,0 @@
|
|||||||
module github.com/mattburchett/go_telegram
|
|
||||||
|
|
||||||
go 1.17
|
|
||||||
|
|
||||||
replace gopkg.in/tucnak/telebot.v2 => github.com/tucnak/telebot v0.0.0-20171121031619-29bd3707020c
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/yanzay/tbot v1.0.0
|
|
||||||
github.com/yanzay/tbot/v2 v2.1.0
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
|
|
||||||
github.com/smartystreets/goconvey v1.7.2 // indirect
|
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
|
||||||
github.com/yanzay/log v0.0.0-20160419144809-87352bb23506 // indirect
|
|
||||||
)
|
|
23
go.sum
23
go.sum
@ -1,23 +0,0 @@
|
|||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
|
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
|
||||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
|
||||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
|
||||||
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
|
||||||
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
|
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
|
||||||
github.com/yanzay/log v0.0.0-20160419144809-87352bb23506 h1:RPrQRi67MUoUPg/3wwL9K9vKVWAB180e2WJgxC02CJE=
|
|
||||||
github.com/yanzay/log v0.0.0-20160419144809-87352bb23506/go.mod h1:x2hAcqPbZzQz79Fzr9xEe7BM73+UsZ3nBucx2u30oSk=
|
|
||||||
github.com/yanzay/tbot v1.0.0 h1:pKLHIvdiHRgU5iTfpWlgMTCWyD4vIQtAsOy7LCYMsAo=
|
|
||||||
github.com/yanzay/tbot v1.0.0/go.mod h1:rS36e4e2P56jkI0bUuZtzjBBIwMIdBBTUHfI4tgG5BM=
|
|
||||||
github.com/yanzay/tbot/v2 v2.1.0 h1:mppieSOIbzaCjp2en66Fz4unIJ57+aalQfdGbtYmaKg=
|
|
||||||
github.com/yanzay/tbot/v2 v2.1.0/go.mod h1:q0+8JblBq9tLAnKHdBIZsHwDvMS9TfO6mNfaAk1VrHg=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
@ -1,56 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config - This struct will hold configuration components.
|
|
||||||
type Config struct {
|
|
||||||
Telegram struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
ChatID string `json:"chatId"`
|
|
||||||
Admins []int `json:"admins"`
|
|
||||||
AuthorizedChats []string `json:"authorizedChats"`
|
|
||||||
} `json:"telegram"`
|
|
||||||
|
|
||||||
Sonarr struct {
|
|
||||||
URL string `json:"url"`
|
|
||||||
APIKey string `json:"apiKey"`
|
|
||||||
SeasonLimit int `json:"seasonLimit"`
|
|
||||||
ProfileID int `json:"profileId"`
|
|
||||||
} `json:"sonarr"`
|
|
||||||
CouchPotato struct {
|
|
||||||
URL string `json:"url"`
|
|
||||||
APIKey string `json:"apiKey"`
|
|
||||||
ProfileID string `json:"profileId`
|
|
||||||
} `json:"couchpotato"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//GetConfig gets the configuration values for the api using the file in the supplied configPath.
|
|
||||||
func GetConfig(configPath string) (Config, error) {
|
|
||||||
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
|
||||||
return Config{}, fmt.Errorf("could not find the config file at path %s", configPath)
|
|
||||||
}
|
|
||||||
log.Println("Loading Configuration File: " + configPath)
|
|
||||||
return loadConfigFromFile(configPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
//if the config loaded from the file errors, no defaults will be loaded and the app will exit.
|
|
||||||
func loadConfigFromFile(configPath string) (conf Config, err error) {
|
|
||||||
file, err := os.Open(configPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error opening config file: %v", err)
|
|
||||||
} else {
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
err = json.NewDecoder(file).Decode(&conf)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error decoding config file: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf, err
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
package couchpotato
|
|
@ -1,87 +0,0 @@
|
|||||||
package couchpotato
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/mattburchett/go_telegram/pkg/core/config"
|
|
||||||
"github.com/yanzay/tbot/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type couchpotatoSearch struct {
|
|
||||||
Movies []struct {
|
|
||||||
Title string `json:"original_title"`
|
|
||||||
Imdb string `json:"imdb"`
|
|
||||||
Year int `json:"year"`
|
|
||||||
InLibrary bool `json:"in_library"`
|
|
||||||
InWanted bool `json:"in_wanted"`
|
|
||||||
} `json:"movies"`
|
|
||||||
Success bool `json:"success"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type request struct {
|
|
||||||
ImdbID string `json:"imdbid"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Year int `json:"year"`
|
|
||||||
Requested bool `json:"requested"`
|
|
||||||
Downloaded bool `json:"downloaded"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (search couchpotatoSearch) Convert() []request {
|
|
||||||
requests := []request{}
|
|
||||||
for _, result := range search.Movies {
|
|
||||||
requests = append(requests, request{
|
|
||||||
ImdbID: result.Imdb,
|
|
||||||
Title: result.Title,
|
|
||||||
Year: result.Year,
|
|
||||||
Requested: result.InWanted,
|
|
||||||
Downloaded: result.InLibrary,
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return requests
|
|
||||||
}
|
|
||||||
|
|
||||||
type response struct {
|
|
||||||
Button string `json:"button"`
|
|
||||||
Callback string `json:"callback"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search performs the lookup actions within CouchPotato
|
|
||||||
func Search(m *tbot.Message, config config.Config) ([]response, error) {
|
|
||||||
searchLookup, err := http.Get(config.CouchPotato.URL + config.CouchPotato.APIKey + "/movie.search?q=" + url.QueryEscape(strings.TrimPrefix(strings.TrimPrefix(m.Text, "/m"), " ")))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
search := couchpotatoSearch{}
|
|
||||||
|
|
||||||
searchData, err := ioutil.ReadAll(searchLookup.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
requestJSON := json.Unmarshal(searchData, &search)
|
|
||||||
if requestJSON != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
requests := search.Convert()
|
|
||||||
|
|
||||||
responseData := []response{}
|
|
||||||
for _, r := range requests {
|
|
||||||
responseData = append(responseData,
|
|
||||||
response{
|
|
||||||
fmt.Sprintf("%v (%v)", r.Title, r.Year),
|
|
||||||
fmt.Sprintf("%v", r.ImdbID),
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return responseData, err
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package sonarr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/mattburchett/go_telegram/pkg/core/config"
|
|
||||||
"github.com/yanzay/tbot/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Status contains the Sonarr request for system status.
|
|
||||||
func Status(m *tbot.Message, config config.Config) (string, error) {
|
|
||||||
r, err := http.Get(config.Sonarr.URL + "system/status?apikey=" + config.Sonarr.APIKey)
|
|
||||||
if err != nil {
|
|
||||||
return "Failed to contact Sonarr for data", err
|
|
||||||
}
|
|
||||||
|
|
||||||
rd, err := ioutil.ReadAll(r.Body)
|
|
||||||
if err != nil {
|
|
||||||
return "Failed to read Sonarr status data.", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(rd), err
|
|
||||||
}
|
|
@ -1,245 +0,0 @@
|
|||||||
package sonarr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/mattburchett/go_telegram/pkg/core/config"
|
|
||||||
"github.com/yanzay/tbot/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Response holds the information needed for Telegram callback.
|
|
||||||
type response struct {
|
|
||||||
Button string `json:"button"`
|
|
||||||
Callback string `json:"callback"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type sonarrSearch []struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
SeasonCount int `json:"seasonCount"`
|
|
||||||
Year int `json:"year"`
|
|
||||||
TvdbID int `json:"tvdbId"`
|
|
||||||
Downloaded bool `json:"downloaded"`
|
|
||||||
QualityProfileID int `json:"qualityProfileId"`
|
|
||||||
TitleSlug string `json:"titleSlug"`
|
|
||||||
Images []struct {
|
|
||||||
CoverType string `json:"coverType"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
} `json:"images"`
|
|
||||||
Seasons []struct {
|
|
||||||
SeasonNumber int `json:"seasonNumber"`
|
|
||||||
Monitored bool `json:"monitored"`
|
|
||||||
} `json:"seasons"`
|
|
||||||
ProfileID int `json:"profileId"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type sonarrAdd struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
TvdbID int `json:"tvdbId"`
|
|
||||||
QualityProfileID int `json:"qualityProfileId"`
|
|
||||||
TitleSlug string `json:"titleSlug"`
|
|
||||||
Images []struct {
|
|
||||||
CoverType string `json:"coverType"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
} `json:"images"`
|
|
||||||
Seasons []struct {
|
|
||||||
SeasonNumber int `json:"seasonNumber"`
|
|
||||||
Monitored bool `json:"monitored"`
|
|
||||||
} `json:"seasons"`
|
|
||||||
ProfileID int `json:"profileId"`
|
|
||||||
RootFolderPath string `json:"rootFolderPath"`
|
|
||||||
AddOptions struct {
|
|
||||||
IgnoreEpisodesWithFiles bool `json:"ignoreEpisodesWithFiles"`
|
|
||||||
IgnoreEpisodesWithoutFiles bool `json:"ignoreEpisodesWithoutFiles"`
|
|
||||||
SearchForMIssingEpisodes bool `json:"searchForMissingEpisodes"`
|
|
||||||
} `json:"addOptions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type rootFolderLookup []struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
FreeSpace int64 `json:"freeSpace"`
|
|
||||||
TotalSpace int64 `json:"totalSpace"`
|
|
||||||
UnmappedFolders []struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
} `json:"unmappedFolders"`
|
|
||||||
ID int `json:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search performs the lookup actions within Sonarr.
|
|
||||||
func Search(m *tbot.Message, config config.Config) ([]response, error) {
|
|
||||||
|
|
||||||
var remote sonarrSearch
|
|
||||||
var local sonarrSearch
|
|
||||||
|
|
||||||
// Perform series lookup
|
|
||||||
remoteLookup, err := http.Get(config.Sonarr.URL +
|
|
||||||
"series/lookup?apikey=" +
|
|
||||||
config.Sonarr.APIKey +
|
|
||||||
"&term=" +
|
|
||||||
url.QueryEscape(strings.TrimPrefix(strings.TrimPrefix(m.Text, "/s"), " ")))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform series local database lookup.
|
|
||||||
localLookup, err := http.Get(config.Sonarr.URL + "series?apikey=" + config.Sonarr.APIKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read remote and local Data
|
|
||||||
remoteData, err := ioutil.ReadAll(remoteLookup.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
localData, err := ioutil.ReadAll(localLookup.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal remote and local JSON
|
|
||||||
remoteJSON := json.Unmarshal(remoteData, &remote)
|
|
||||||
if remoteJSON != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
localJSON := json.Unmarshal(localData, &local)
|
|
||||||
if localJSON != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for downloaded items.
|
|
||||||
for r := range remote {
|
|
||||||
for l := range local {
|
|
||||||
if remote[r].TvdbID == local[l].TvdbID {
|
|
||||||
remote[r].Downloaded = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Form URLs and return to Telegram
|
|
||||||
responseData := []response{}
|
|
||||||
for k := range remote {
|
|
||||||
responseData = append(responseData,
|
|
||||||
response{
|
|
||||||
fmt.Sprintf("%v%v%v (%v) - %v Seasons",
|
|
||||||
seasonHandler(remote[k].SeasonCount, config.Sonarr.SeasonLimit),
|
|
||||||
downloadedHandler(remote[k].Downloaded),
|
|
||||||
remote[k].Title,
|
|
||||||
remote[k].Year,
|
|
||||||
remote[k].SeasonCount),
|
|
||||||
fmt.Sprintf("%d%s%s", remote[k].TvdbID,
|
|
||||||
strings.TrimSuffix(downloadedHandler(remote[k].Downloaded), " "),
|
|
||||||
strings.TrimSuffix(seasonHandler(remote[k].SeasonCount, config.Sonarr.SeasonLimit), " ")),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return responseData, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add will take the callback data and add the show to Sonarr.
|
|
||||||
func Add(callback string, config config.Config) string {
|
|
||||||
// Separate the TVDB ID
|
|
||||||
tvdbid := strings.TrimPrefix(strings.TrimSuffix(strings.TrimSuffix(callback, "+"), "*"), "tv_")
|
|
||||||
|
|
||||||
// Look it up, to gather the information needed and the title.
|
|
||||||
seriesLookup, err := http.Get(config.Sonarr.URL + "/series/lookup?apikey=" + config.Sonarr.APIKey + "&term=tvdb:" + tvdbid)
|
|
||||||
if err != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
seriesData, err := ioutil.ReadAll(seriesLookup.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
series := sonarrSearch{}
|
|
||||||
seriesJSON := json.Unmarshal(seriesData, &series)
|
|
||||||
if seriesJSON != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the "downloaded" asterisk is already in place, go ahead and return.
|
|
||||||
if strings.Contains(callback, "*") {
|
|
||||||
return fmt.Sprintf("%v has already been requested for download.", series[0].Title)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gather the root folder location.
|
|
||||||
rootFolderLookupQuery, err := http.Get(config.Sonarr.URL + "/rootfolder?apikey=" + config.Sonarr.APIKey)
|
|
||||||
if err != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
rootFolderData, err := ioutil.ReadAll(rootFolderLookupQuery.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
rootFolder := rootFolderLookup{}
|
|
||||||
rootFolderJSON := json.Unmarshal(rootFolderData, &rootFolder)
|
|
||||||
if rootFolderJSON != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Form the JSON needed for adding to Sonarr.
|
|
||||||
seriesAdd := sonarrAdd{
|
|
||||||
TvdbID: series[0].TvdbID,
|
|
||||||
Title: series[0].Title,
|
|
||||||
// QualityProfileID: series[0].QualityProfileID,
|
|
||||||
TitleSlug: series[0].TitleSlug,
|
|
||||||
Images: series[0].Images,
|
|
||||||
Seasons: series[0].Seasons,
|
|
||||||
RootFolderPath: rootFolder[0].Path,
|
|
||||||
ProfileID: config.Sonarr.ProfileID,
|
|
||||||
}
|
|
||||||
seriesAdd.AddOptions.IgnoreEpisodesWithFiles = false
|
|
||||||
seriesAdd.AddOptions.IgnoreEpisodesWithoutFiles = false
|
|
||||||
seriesAdd.AddOptions.SearchForMIssingEpisodes = true
|
|
||||||
|
|
||||||
// Post it to Sonarr to be added.
|
|
||||||
seriesAddJSON, err := json.Marshal(seriesAdd)
|
|
||||||
if err != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
seriesAddReq, err := http.Post(config.Sonarr.URL+"/series?apikey="+config.Sonarr.APIKey, "application/json", bytes.NewBuffer(seriesAddJSON))
|
|
||||||
if err != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
if seriesAddReq.StatusCode != 201 {
|
|
||||||
return "There was an error processing this request."
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s has been queued for download.", series[0].Title)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// downloadHandler returns the proper string that should be shown in the Telegram response.
|
|
||||||
func downloadedHandler(downloaded bool) string {
|
|
||||||
if downloaded {
|
|
||||||
return "* "
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// seasonHandler returns the proper string that should be shown in the Telegram response.
|
|
||||||
// it is also used to prevent non-admins from downloading shows with a high number of seasons.
|
|
||||||
func seasonHandler(seasonCount int, seasonLimit int) string {
|
|
||||||
if seasonLimit == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if seasonCount >= seasonLimit {
|
|
||||||
return "+ "
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package telegram
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/yanzay/tbot/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (tb *Bot) myID(m *tbot.Message) {
|
|
||||||
if tb.adminCheck(m.From.ID, false) {
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, strconv.Itoa(m.From.ID))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, "You are not an authorized admin.")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tb *Bot) chatID(m *tbot.Message) {
|
|
||||||
if tb.adminCheck(m.From.ID, false) {
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, m.Chat.ID)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, "You are not an authorized admin.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// adminCheck checks for valid bot admins.
|
|
||||||
func (tb *Bot) adminCheck(id int, callback bool) bool {
|
|
||||||
for _, admin := range tb.Config.Telegram.Admins {
|
|
||||||
if id == admin {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
package telegram
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/yanzay/tbot/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Handler creates the active Telegram handlers.
|
|
||||||
func (tb *Bot) Handler() {
|
|
||||||
|
|
||||||
// Bot Healthcheck
|
|
||||||
tb.Bot.HandleMessage("/ping", func(m *tbot.Message) {
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, "pong")
|
|
||||||
})
|
|
||||||
|
|
||||||
// telegram/couchpotato.go
|
|
||||||
tb.Bot.HandleMessage("/m", tb.couchpotatoSearch)
|
|
||||||
|
|
||||||
// telegram/sonar.go
|
|
||||||
tb.Bot.HandleMessage("/s", tb.sonarrSearch)
|
|
||||||
tb.Bot.HandleMessage("/admin sonarrStatus", tb.sonarrStatus)
|
|
||||||
|
|
||||||
// telegram/testhandler.go
|
|
||||||
tb.Bot.HandleMessage("/test", tb.testHandler)
|
|
||||||
|
|
||||||
// telegram/admin.go
|
|
||||||
tb.Bot.HandleMessage("/admin myID", tb.myID)
|
|
||||||
tb.Bot.HandleMessage("/admin chatID", tb.chatID)
|
|
||||||
|
|
||||||
// Help
|
|
||||||
tb.Bot.HandleMessage("/help$", tb.helpHandler)
|
|
||||||
tb.Bot.HandleMessage("/h$", tb.helpHandler)
|
|
||||||
|
|
||||||
// Callback Handler
|
|
||||||
tb.Bot.HandleCallback(tb.callbackHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// callbackHandler handles callbacks.
|
|
||||||
func (tb *Bot) callbackHandler(cq *tbot.CallbackQuery) {
|
|
||||||
go func() {
|
|
||||||
tb.Client.AnswerCallbackQuery(cq.ID, tbot.OptText("Request received."))
|
|
||||||
tb.Client.DeleteMessage(tb.CallbackChatID, tb.CallbackMessageID)
|
|
||||||
}()
|
|
||||||
|
|
||||||
if strings.Contains(cq.Data, "tv_") {
|
|
||||||
tb.sonarrAdd(cq)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tb.Client.SendMessage(tb.CallbackChatID, cq.Data)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tb *Bot) helpHandler(m *tbot.Message) {
|
|
||||||
if !tb.whitelistHandler(m) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, "USAGE:\n\n/movie <Movie Name> or /m <Movie Name>\n/show <TV Show Name> or /s <TV Show Name>\n\nEXAMPLES:\n\n/s The Walking Dead\n/m Avatar")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tb *Bot) whitelistHandler(m *tbot.Message) bool {
|
|
||||||
for _, id := range tb.Config.Telegram.AuthorizedChats {
|
|
||||||
if id == m.Chat.ID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, "This bot is not authorized for use in this chat.")
|
|
||||||
return false
|
|
||||||
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
package telegram
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/mattburchett/go_telegram/pkg/service/sonarr"
|
|
||||||
|
|
||||||
"github.com/yanzay/tbot/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sonarr Search
|
|
||||||
func (tb *Bot) sonarrSearch(m *tbot.Message) {
|
|
||||||
if !tb.whitelistHandler(m) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
text := strings.TrimPrefix(strings.TrimPrefix(m.Text, "/s"), " ")
|
|
||||||
if len(text) == 0 {
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, "You must specify a show. Type /help for help.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
request, err := sonarr.Search(m, tb.Config)
|
|
||||||
if err != nil {
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
inlineResponse := make([][]tbot.InlineKeyboardButton, 0)
|
|
||||||
for _, i := range request {
|
|
||||||
inlineResponse = append(inlineResponse, []tbot.InlineKeyboardButton{{
|
|
||||||
Text: i.Button,
|
|
||||||
CallbackData: "tv_" + i.Callback,
|
|
||||||
}})
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(request) == 0 {
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, "No results found, try harder.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response, _ := tb.Client.SendMessage(m.Chat.ID, "Please select the show you would like to download.", tbot.OptInlineKeyboardMarkup(&tbot.InlineKeyboardMarkup{InlineKeyboard: inlineResponse}))
|
|
||||||
tb.CallbackMessageID = response.MessageID
|
|
||||||
tb.CallbackChatID = m.Chat.ID
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// sonarrAdd will perform the add requests to Sonarr.
|
|
||||||
func (tb *Bot) sonarrAdd(cq *tbot.CallbackQuery) {
|
|
||||||
if strings.Contains(cq.Data, "+") {
|
|
||||||
if tb.adminCheck(cq.From.ID, true) {
|
|
||||||
tb.Client.SendMessage(tb.CallbackChatID, sonarr.Add(cq.Data, tb.Config))
|
|
||||||
} else {
|
|
||||||
tb.Client.AnswerCallbackQuery(cq.ID, tbot.OptText("This request is over the season limit."))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tb.Client.SendMessage(tb.CallbackChatID, sonarr.Add(cq.Data, tb.Config))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Admin Functions
|
|
||||||
|
|
||||||
// sonarrStatus queries Sonarr for it's system status information.
|
|
||||||
func (tb *Bot) sonarrStatus(m *tbot.Message) {
|
|
||||||
if !tb.whitelistHandler(m) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if tb.adminCheck(m.From.ID, false) {
|
|
||||||
request, err := sonarr.Status(m, tb.Config)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, fmt.Sprintf("%v: \n %v", request, err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, "Sonarr Status:")
|
|
||||||
tb.Client.SendMessage(m.Chat.ID, request)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package telegram
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/mattburchett/go_telegram/pkg/core/config"
|
|
||||||
"github.com/yanzay/tbot/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bot contains all the necessary bot and callback information.
|
|
||||||
type Bot struct {
|
|
||||||
Client *tbot.Client
|
|
||||||
Config config.Config
|
|
||||||
Bot *tbot.Server
|
|
||||||
CallbackChatID string
|
|
||||||
CallbackMessageID int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stat middleware.
|
|
||||||
func stat(h tbot.UpdateHandler) tbot.UpdateHandler {
|
|
||||||
return func(u *tbot.Update) {
|
|
||||||
start := time.Now()
|
|
||||||
h(u)
|
|
||||||
log.Printf("Handle time: %v", time.Now().Sub(start))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates an active telegram bot and loads the handlers.
|
|
||||||
func (tb *Bot) New(token string) {
|
|
||||||
tb.Bot = tbot.New(token)
|
|
||||||
tb.Bot.Use(stat)
|
|
||||||
tb.Client = tb.Bot.Client()
|
|
||||||
tb.Handler()
|
|
||||||
tb.Bot.Start()
|
|
||||||
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package telegram
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/yanzay/tbot/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (tb *Bot) testHandler(m *tbot.Message) {
|
|
||||||
buttons := make([]string, 0)
|
|
||||||
buttons = append(buttons, "ping", "is", "stupid")
|
|
||||||
|
|
||||||
inline2 := make([][]tbot.InlineKeyboardButton, 0)
|
|
||||||
|
|
||||||
for _, i := range buttons {
|
|
||||||
inline2 = append(inline2, []tbot.InlineKeyboardButton{{
|
|
||||||
Text: i,
|
|
||||||
CallbackData: i,
|
|
||||||
}})
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, _ := tb.Client.SendMessage(m.Chat.ID, "Inline test. "+strings.TrimPrefix(m.Text, "/test "), tbot.OptInlineKeyboardMarkup(&tbot.InlineKeyboardMarkup{InlineKeyboard: inline2}))
|
|
||||||
tb.CallbackMessageID = msg.MessageID
|
|
||||||
tb.CallbackChatID = m.Chat.ID
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user