initial commit
This commit is contained in:
92
parser/client.go
Normal file
92
parser/client.go
Normal file
@ -0,0 +1,92 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/gmail/v1"
|
||||
)
|
||||
|
||||
// Client .
|
||||
func Client() *gmail.Service {
|
||||
b, err := ioutil.ReadFile("./credentials/credentials.json")
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to read client secret file: %v", err)
|
||||
}
|
||||
|
||||
// If modifying these scopes, delete your previously saved token.json.
|
||||
config, err := google.ConfigFromJSON(b, gmail.GmailModifyScope)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to parse client secret file to config: %v", err)
|
||||
}
|
||||
client := getClient(config)
|
||||
|
||||
srv, err := gmail.New(client)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to retrieve Gmail client: %v", err)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
// Retrieve a token, saves the token, then returns the generated client.
|
||||
func getClient(config *oauth2.Config) *http.Client {
|
||||
// The file token.json stores the user's access and refresh tokens, and is
|
||||
// created automatically when the authorization flow completes for the first
|
||||
// time.
|
||||
tokFile := "./credentials/token.json"
|
||||
tok, err := tokenFromFile(tokFile)
|
||||
if err != nil {
|
||||
tok = getTokenFromWeb(config)
|
||||
saveToken(tokFile, tok)
|
||||
}
|
||||
return config.Client(context.Background(), tok)
|
||||
}
|
||||
|
||||
// Request a token from the web, then returns the retrieved token.
|
||||
func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
|
||||
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
|
||||
fmt.Printf("Go to the following link in your browser then type the "+
|
||||
"authorization code: \n%v\n", authURL)
|
||||
|
||||
var authCode string
|
||||
if _, err := fmt.Scan(&authCode); err != nil {
|
||||
log.Fatalf("Unable to read authorization code: %v", err)
|
||||
}
|
||||
|
||||
tok, err := config.Exchange(context.TODO(), authCode)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to retrieve token from web: %v", err)
|
||||
}
|
||||
return tok
|
||||
}
|
||||
|
||||
// Retrieves a token from a local file.
|
||||
func tokenFromFile(file string) (*oauth2.Token, error) {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
tok := &oauth2.Token{}
|
||||
err = json.NewDecoder(f).Decode(tok)
|
||||
|
||||
return tok, err
|
||||
}
|
||||
|
||||
// Saves a token to a file path.
|
||||
func saveToken(path string, token *oauth2.Token) {
|
||||
fmt.Printf("Saving credential file to: %s\n", path)
|
||||
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to cache oauth token: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
json.NewEncoder(f).Encode(token)
|
||||
}
|
144
parser/message.go
Normal file
144
parser/message.go
Normal file
@ -0,0 +1,144 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"html"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/api/gmail/v1"
|
||||
)
|
||||
|
||||
// Message .
|
||||
type Message struct {
|
||||
gmailID string
|
||||
date string // retrieved from message header
|
||||
snippet string
|
||||
}
|
||||
|
||||
// GetMessages .
|
||||
func GetMessages(srv *gmail.Service) []Message {
|
||||
msgs := []Message{}
|
||||
pageToken := ""
|
||||
for {
|
||||
req := srv.Users.Messages.List("me").Q("is:unread").Q("from:messaging@iamresponding.com")
|
||||
// req := srv.Users.Messages.List("me").Q("is:unread")
|
||||
if pageToken != "" {
|
||||
req.PageToken(pageToken)
|
||||
}
|
||||
r, err := req.Do()
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to retrieve messages: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("Processing %v messages...\n", len(r.Messages))
|
||||
for _, m := range r.Messages {
|
||||
msg, err := srv.Users.Messages.Get("me", m.Id).Format("full").Do()
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to retrieve message %v: %v", m.Id, err)
|
||||
}
|
||||
date := ""
|
||||
for _, h := range msg.Payload.Headers {
|
||||
if h.Name == "Date" {
|
||||
date = h.Value
|
||||
}
|
||||
// break
|
||||
}
|
||||
|
||||
msgs = append(msgs, Message{
|
||||
gmailID: msg.Id,
|
||||
date: date,
|
||||
snippet: html.UnescapeString(msg.Snippet),
|
||||
})
|
||||
}
|
||||
|
||||
if r.NextPageToken == "" {
|
||||
break
|
||||
}
|
||||
pageToken = r.NextPageToken
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
count, deleted := 0, 0
|
||||
for _, m := range msgs {
|
||||
count++
|
||||
|
||||
re := regexp.MustCompile(`^(?P<address>[^\s\[\[].*)\s\[\[(?P<city>[^\]\]].*)\]\]\s\((?P<type>[^\)].*)\)\s\-\s(?P<description>.*?)(?P<phone>\(\d{3}\)\s\d{3}\-\d{4})?\s?(?:F\d{9})?\s?(?:\d{7})?\s?(?P<time>\d{2}\:\d{2})?$`)
|
||||
if re.Match([]byte(m.snippet)) {
|
||||
|
||||
groups := re.SubexpNames()
|
||||
result := re.FindAllStringSubmatch(m.snippet, -1)
|
||||
|
||||
rt := map[string]string{}
|
||||
for i, n := range result[0] {
|
||||
rt[groups[i]] = n
|
||||
}
|
||||
|
||||
fmt.Printf("=============================================================\n")
|
||||
fmt.Printf("Message URL: https://mail.google.com/mail/u/0/#all/%v\n", m.gmailID)
|
||||
fmt.Printf("Snippet: %q\n", m.snippet)
|
||||
if value, ok := rt["address"]; ok {
|
||||
fmt.Printf("Address: %s\n", value)
|
||||
} else {
|
||||
fmt.Print("There is no address value\n")
|
||||
}
|
||||
if value, ok := rt["city"]; ok {
|
||||
fmt.Printf("City: %s\n", value)
|
||||
} else {
|
||||
fmt.Print("There is no city value\n")
|
||||
}
|
||||
if value, ok := rt["type"]; ok {
|
||||
fmt.Printf("Type: %s\n", value)
|
||||
} else {
|
||||
fmt.Print("There is no type value\n")
|
||||
}
|
||||
if value, ok := rt["description"]; ok {
|
||||
fmt.Printf("Description: %s\n", value)
|
||||
} else {
|
||||
fmt.Print("There is no description value\n")
|
||||
}
|
||||
if value, ok := rt["phone"]; ok {
|
||||
fmt.Printf("Phone: %s\n", value)
|
||||
} else {
|
||||
fmt.Print("There is no phone value\n")
|
||||
}
|
||||
if value, ok := rt["time"]; ok {
|
||||
fmt.Printf("Time: %s\n", value)
|
||||
} else {
|
||||
fmt.Print("There is no time value\n")
|
||||
}
|
||||
fmt.Printf("Date: %v\n", m.date)
|
||||
fmt.Printf("=============================================================\n")
|
||||
fmt.Printf("Options: (d)elete, (r)ead, (p)rint, (s)kip, (q)uit: [s] ")
|
||||
val := ""
|
||||
if _, err := reader.ReadString('\n'); err != nil {
|
||||
log.Fatalf("unable to scan input: %v", err)
|
||||
}
|
||||
val = strings.TrimSpace(val)
|
||||
switch val {
|
||||
case "d": // delete message
|
||||
if err := srv.Users.Messages.Delete("me", m.gmailID).Do(); err != nil {
|
||||
log.Fatalf("unable to delete message %v: %v", m.gmailID, err)
|
||||
}
|
||||
log.Printf("Deleted message %v.\n", m.gmailID)
|
||||
deleted++
|
||||
case "r": // mark as read
|
||||
msg, err := srv.Users.Messages.Modify("me", m.gmailID, &gmail.ModifyMessageRequest{RemoveLabelIds: []string{"UNREAD"}}).Do()
|
||||
if err != nil {
|
||||
log.Fatalf("unable to modify message %v: %v", m.gmailID, err)
|
||||
}
|
||||
log.Printf("Modified message %v.\n", msg)
|
||||
case "q": // quit
|
||||
log.Printf("Done. %v messages processed, %v deleted\n", count, deleted)
|
||||
os.Exit(0)
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return msgs
|
||||
}
|
Reference in New Issue
Block a user