package main import ( "context" "fmt" "log" "net/url" "os" "path/filepath" "regexp" "time" "github.com/go-yaml/yaml" "github.com/mattn/go-mastodon" "github.com/mmcdole/gofeed" "github.com/urfave/cli/v3" ) type MastodonClientData struct { ClientID string `yaml:"clientID,omitempty"` ClientSecret string `yaml:"clientSecret,omitempty"` AccessToken string `yaml:"accessToken,omitempty"` Instance string `yaml:"instance,omitempty"` } type KikiSettings struct { Instance string `yaml:"instance,omitempty"` RSSUri string `yaml:"rss_url,omitempty"` } func getDataFromConfig(path string) *mastodon.Config { var clientData MastodonClientData secretConfig, err := os.ReadFile(path) if err != nil { log.Println(err) } err = yaml.Unmarshal(secretConfig, &clientData) if err != nil { log.Println(err) } config := &mastodon.Config{ Server: clientData.Instance, ClientID: clientData.ClientID, ClientSecret: clientData.ClientSecret, AccessToken: clientData.AccessToken, } return config } func hasHTMLTags(s string) bool { re := regexp.MustCompile(`<(?i)[a-z][a-z0-9]*[^>]*>`) return re.MatchString(s) } func getKikiConfig(path string) KikiSettings { var kikiSettings KikiSettings kikiConfigFile, err := os.ReadFile(path) if err != nil { log.Println(err) } err = yaml.Unmarshal(kikiConfigFile, &kikiSettings) if err != nil { log.Println(err) } return kikiSettings } func ClientConfiguration(Instance string) { appConfig := &mastodon.AppConfig{ Server: Instance, ClientName: "Kiki", Scopes: "read write follow", Website: "catgirls.asia", RedirectURIs: "urn:ietf:wg:oauth:2.0:oob", } app, err := mastodon.RegisterApp(context.Background(), appConfig) if err != nil { log.Println(err) } u, err := url.Parse(app.AuthURI) if err != nil { log.Println(err) } var userToken string fmt.Println(u) fmt.Scanln(&userToken) config := &mastodon.Config{ Server: Instance, ClientID: app.ClientID, ClientSecret: app.ClientSecret, AccessToken: userToken, } mastoClient := mastodon.NewClient(config) err = mastoClient.AuthenticateToken(context.Background(), userToken, "urn:ietf:wg:oauth:2.0:oob") if err != nil { log.Println(err) } clientData := MastodonClientData{ Instance: Instance, ClientID: mastoClient.Config.ClientID, ClientSecret: mastoClient.Config.ClientSecret, AccessToken: mastoClient.Config.AccessToken, } marshaledYaml, err := yaml.Marshal(clientData) if err != nil { log.Println(err) } secretConfig, err := os.OpenFile("secret.conf", os.O_CREATE, 0o644) if err != nil { log.Println(err) } secretConfig.WriteString(string(marshaledYaml)) } func newsText(url string) []*gofeed.Item { fp := gofeed.NewParser() feed, err := fp.ParseURL(url) if err != nil { log.Println(err) } log.Println("RSS лента получена") return feed.Items } func createPost(statusText string) { config := getDataFromConfig("secret.conf") mastoClient := mastodon.NewClient(config) toot := mastodon.Toot{ Status: statusText, Visibility: "unlisted", } _, err := mastoClient.PostStatus(context.Background(), &toot) if err != nil { log.Println(err) } } func main() { cmd := &cli.Command{ Name: "kiki", Usage: "Ретранслятор из RSS в Mastodon. Когда-нибудь...", Commands: []*cli.Command{ { Name: "init", Usage: "Инициализировать клиента", Action: func(ctx context.Context, cmd *cli.Command) error { confFile, err := filepath.Abs("config.yaml") if err != nil { log.Println(err) } kikiConfig := getKikiConfig(confFile) instanceUrlParser, err := url.Parse(kikiConfig.Instance) if err != nil { log.Println(err) } instanceUrlParser.Scheme = "https" ClientConfiguration(instanceUrlParser.String()) return nil }, }, { Name: "run", Usage: "Запуск транслятора", Action: func(ctx context.Context, cmd *cli.Command) error { var lastGUID string confFile, err := filepath.Abs("config.yaml") if err != nil { log.Println(err) } kikiConfig := getKikiConfig(confFile) ticker := time.NewTicker(1 * time.Minute) defer ticker.Stop() for range ticker.C { news := newsText(kikiConfig.RSSUri) if news[0].GUID != lastGUID { if !hasHTMLTags(news[0].Description) { createPost(news[0].Description) lastGUID = news[0].GUID log.Println("Пост отправлен") } } /*for _, item := range newsText(kikiConfig.RSSUri) { if item.GUID == lastGUID { break } createPost(item.Description) lastGUID = item.GUID log.Println("Пост отправлен") }*/ } return nil }, }, }, } if err := cmd.Run(context.Background(), os.Args); err != nil { log.Fatal(err) } }