diff --git a/README.md b/README.md index 5738c237..007ea13e 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ _ = notifier.Send( - *Discord* - *Email* +- *Instagram* - *Mailgun* - *Microsoft Teams* - *Plivo* @@ -81,6 +82,7 @@ _ = notifier.Send( - Discord support: [bwmarrin/discordgo](https://github.com/bwmarrin/discordgo) - Email support: [jordan-wright/email](https://github.com/jordan-wright/email) +- Instagram support: [ahmdrz/goinsta](https://github.com/ahmdrz/goinsta) - Logo: [MariaLetta/free-gophers-pack](https://github.com/MariaLetta/free-gophers-pack) - Mailgun support: [mailgun/mailgun-go](https://github.com/mailgun/mailgun-go) - Microsoft Teams support: [atc0005/go-teams-notify](https://github.com/atc0005/go-teams-notify) diff --git a/go.mod b/go.mod index 1fdb216f..ebddf6bd 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/nikoksr/notify go 1.15 require ( + github.com/ahmdrz/goinsta/v2 v2.4.5 github.com/atc0005/go-teams-notify/v2 v2.4.2 github.com/bwmarrin/discordgo v0.23.2 github.com/cenkalti/backoff v2.2.1+incompatible // indirect diff --git a/go.sum b/go.sum index 5e53f222..f0e12d4e 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/ahmdrz/goinsta/v2 v2.4.5 h1:yiNEpTNEx/VWlcCq93miWUx6d2uxdEyklwljsZaiD5I= +github.com/ahmdrz/goinsta/v2 v2.4.5/go.mod h1:XUEELCWd3hVSqADejqxTa8Uc7Yto9cb6a6HrfkGwVf8= github.com/atc0005/go-teams-notify/v2 v2.4.2 h1:3KQ8e8LN4kwuWWHpnCNTXA15JdLRaNWcCS1VS0a4SO0= github.com/atc0005/go-teams-notify/v2 v2.4.2/go.mod h1:BSlh1HBcgWcGoNM3Abm36WMPcj+k8Wf0ZLZx6lBx2qk= github.com/bwmarrin/discordgo v0.23.2 h1:BzrtTktixGHIu9Tt7dEE6diysEF9HWnXeHuoJEt2fH4= diff --git a/service/instagram/instagram.go b/service/instagram/instagram.go new file mode 100644 index 00000000..96b62260 --- /dev/null +++ b/service/instagram/instagram.go @@ -0,0 +1,69 @@ +package instagram + +import ( + "fmt" + "log" + + "github.com/ahmdrz/goinsta/v2" + "github.com/pkg/errors" +) + +// Instagram struct holds necessary data to communicate with the unofficial Instagram API. +type Instagram struct { + client *goinsta.Instagram + usernames []string +} + +// New returns a new instance of a Instagram notification service. +func New(username, password string) (*Instagram, error) { + client := goinsta.New(username, password) + err := client.Login() + if err != nil { + return nil, err + } + + insta := &Instagram{ + client: client, + usernames: []string{}, + } + + return insta, nil +} + +// AddReceivers takes Instagram usernames and adds them to the internal usernames list. +// The Send method will send a given message to all those users. +func (i *Instagram) AddReceivers(usernames ...string) { + i.usernames = append(i.usernames, usernames...) +} + +// Send takes a message subject and a message body and sends them to all previously set users. +func (i Instagram) Send(subject, message string) error { + fullMessage := subject + "\n" + message + for _, username := range i.usernames { + // Search finds users with from most similar to least similar usernames + result, err := i.client.Search.User(username) + if err != nil { + log.Println(err.Error()) + return err + } + user := result.Users[0] + if user.Username == username { + // Doc says to use Conversation.Send for messages after initial message. + // But seems like Inbox.New works for further messages, and Instagram.Conversation doesn't show any conversations. + err = i.client.Inbox.New(&user, fullMessage) + if err != nil { + return errors.Wrapf(err, "failed to send message to Instagram user '%s'", username) + } + } else { + cause := fmt.Errorf("the closest username found is '%s'", user.Username) + return errors.Wrapf(cause, "failed to find the user with username '%s'", username) + } + } + + return nil +} + +// Logout closes the current session to the API +func (i *Instagram) Logout() error { + return i.client.Logout() +} diff --git a/service/instagram/usage.md b/service/instagram/usage.md new file mode 100644 index 00000000..463abcd0 --- /dev/null +++ b/service/instagram/usage.md @@ -0,0 +1,47 @@ +# Instagram Usage + +Ensure that you have already navigated to your GOPATH and installed the following packages: + +* `go get -u github.com/nikoksr/notify` +* `go get github.com/ahmdrz/goinsta/v2` - You might need this one too + + +## Sample Code + +```go +package main + +import ( + "github.com/nikoksr/notify" + "github.com/nikoksr/notify/service/instagram" +) + +func main() { + + notifier := notify.New() + + // Assuming you already have an Instagram account + // Provide your Instagram username and password + service := instagram.New("Username", "Password") + + // Passing usernames as receivers for our messages. + service.AddReceivers("friend1", "friend2") + + // Tell our notifier to use the Instagram service. You can repeat the above process + // for as many services as you like and just tell the notifier to use them. + notifier.UseServices(service) + + // Send a message + err := notifier.Send( + "Hello\n", + "I am a bot written in Go!", + ) + + if err != nil { + panic(err) + } + + // This is Instagram specific, logout after you are done to close the session. + service.Logout() +} +``` \ No newline at end of file