mirror of
				https://github.com/taigrr/godns
				synced 2025-01-18 04:03:25 -08:00 
			
		
		
		
	Add support to telegram notification
This commit is contained in:
		
							parent
							
								
									e5f9076259
								
							
						
					
					
						commit
						f5a793a907
					
				
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							| @ -337,6 +337,7 @@ Update config file and provide your SMTP options, a notification mail will be se | ||||
| 
 | ||||
| ```json | ||||
|   "notify": { | ||||
|     "mail": { | ||||
|       "enabled": true, | ||||
|       "smtp_server": "smtp.example.com", | ||||
|       "smtp_username": "user", | ||||
| @ -344,12 +345,29 @@ Update config file and provide your SMTP options, a notification mail will be se | ||||
|       "smtp_port": 25, | ||||
|       "send_to": "my_mail@example.com" | ||||
|     } | ||||
|   } | ||||
| ``` | ||||
| 
 | ||||
| Notification mail example:   | ||||
| 
 | ||||
| <img src="https://github.com/TimothyYe/godns/blob/master/snapshots/mail.png?raw=true" />   | ||||
| 
 | ||||
| ### Telegram notification support | ||||
| 
 | ||||
| Update config file and provide your Telegram options, a notification message will be sent to your telegram channel once the IP is changed and updated.   | ||||
| 
 | ||||
| ```json | ||||
|   "notify": { | ||||
|     "telegram": { | ||||
|       "enabled": true, | ||||
|       "bot_api_key": "11111:aaaa-bbbb", | ||||
|       "chat_id": "-123456", | ||||
|       "message_template": "Domain *{{ .Domain }}* is updated to %0A{{ .CurrentIP }}" | ||||
|     }, | ||||
|   } | ||||
| ``` | ||||
| Markdown is supported in message template, and use `%0A` for newline. | ||||
| 
 | ||||
| ### SOCKS5 proxy support | ||||
| 
 | ||||
| You can also use SOCKS5 proxy, just fill SOCKS5 address to the ```socks5_proxy``` item: | ||||
|  | ||||
| @ -26,6 +26,13 @@ | ||||
|   "ip_interface": "eth0", | ||||
|   "socks5_proxy": "", | ||||
|   "notify": { | ||||
|     "telegram": { | ||||
|       "enabled": false, | ||||
|       "bot_api_key": "", | ||||
|       "chat_id": "", | ||||
|       "message_template": "" | ||||
|     }, | ||||
|     "mail": { | ||||
|       "enabled": false, | ||||
|       "smtp_server": "", | ||||
|       "smtp_username": "", | ||||
| @ -33,4 +40,5 @@ | ||||
|       "smtp_port": 25, | ||||
|       "send_to": "" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -62,15 +62,12 @@ func (handler *Handler) DomainLoop(domain *godns.Domain, panicChan chan<- godns. | ||||
| 					log.Printf("IP updated for subdomain:%s\r\n", subDomain) | ||||
| 				} | ||||
| 
 | ||||
| 				// Send mail notification if notify is enabled | ||||
| 				if handler.Configuration.Notify.Enabled { | ||||
| 					log.Print("Sending notification to:", handler.Configuration.Notify.SendTo) | ||||
| 				// Send notification | ||||
| 				if err := godns.SendNotify(handler.Configuration, fmt.Sprintf("%s.%s", subDomain, domain.DomainName), currentIP); err != nil { | ||||
| 					log.Printf("Failed to send notification") | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		} | ||||
| 		// Sleep with interval | ||||
| 		log.Printf("Going to sleep, will start next checking in %d seconds...\r\n", handler.Configuration.Interval) | ||||
| 		time.Sleep(time.Second * time.Duration(handler.Configuration.Interval)) | ||||
|  | ||||
| @ -105,13 +105,10 @@ func (handler *Handler) DomainLoop(domain *godns.Domain, panicChan chan<- godns. | ||||
| 						log.Printf("IP mismatch: Current(%+v) vs Cloudflare(%+v)\r\n", currentIP, rec.IP) | ||||
| 						handler.updateRecord(rec, currentIP) | ||||
| 
 | ||||
| 						// Send mail notification if notify is enabled | ||||
| 						if handler.Configuration.Notify.Enabled { | ||||
| 							log.Print("Sending notification to:", handler.Configuration.Notify.SendTo) | ||||
| 						// Send notification | ||||
| 						if err := godns.SendNotify(handler.Configuration, rec.Name, currentIP); err != nil { | ||||
| 							log.Println("Failed to send notification") | ||||
| 						} | ||||
| 						} | ||||
| 					} else { | ||||
| 						log.Printf("Record OK: %+v - %+v\r\n", rec.Name, rec.IP) | ||||
| 					} | ||||
|  | ||||
| @ -73,14 +73,10 @@ func (handler *Handler) DomainLoop(domain *godns.Domain, panicChan chan<- godns. | ||||
| 					log.Printf("%s.%s Start to update record IP...\n", subDomain, domain.DomainName) | ||||
| 					handler.UpdateIP(domainID, subDomainID, subDomain, currentIP) | ||||
| 
 | ||||
| 					// Send mail notification if notify is enabled | ||||
| 					if handler.Configuration.Notify.Enabled { | ||||
| 						log.Print("Sending notification to:", handler.Configuration.Notify.SendTo) | ||||
| 					// Send notification | ||||
| 					if err := godns.SendNotify(handler.Configuration, fmt.Sprintf("%s.%s", subDomain, domain.DomainName), currentIP); err != nil { | ||||
| 						log.Println("Failed to send notification") | ||||
| 					} | ||||
| 					} | ||||
| 
 | ||||
| 				} else { | ||||
| 					log.Printf("%s.%s Current IP is same as domain IP, no need to update...\n", subDomain, domain.DomainName) | ||||
| 				} | ||||
|  | ||||
| @ -79,15 +79,12 @@ func (handler *Handler) DomainLoop(domain *godns.Domain, panicChan chan<- godns. | ||||
| 					log.Print("IP updated to:", currentIP) | ||||
| 				} | ||||
| 
 | ||||
| 				// Send mail notification if notify is enabled | ||||
| 				if handler.Configuration.Notify.Enabled { | ||||
| 					log.Print("Sending notification to:", handler.Configuration.Notify.SendTo) | ||||
| 				// Send notification | ||||
| 				if err := godns.SendNotify(handler.Configuration, fmt.Sprintf("%s.%s", subDomain, domain.DomainName), currentIP); err != nil { | ||||
| 					log.Println("Failed to send notification") | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		} | ||||
| 
 | ||||
| 		// Sleep with interval | ||||
| 		log.Printf("Going to sleep, will start next checking in %d seconds...\r\n", handler.Configuration.Interval) | ||||
|  | ||||
| @ -58,15 +58,12 @@ func (handler *Handler) DomainLoop(domain *godns.Domain, panicChan chan<- godns. | ||||
| 				log.Printf("%s.%s Start to update record IP...\n", subDomain, domain.DomainName) | ||||
| 				handler.UpdateIP(domain.DomainName, subDomain, currentIP) | ||||
| 
 | ||||
| 				// Send mail notification if notify is enabled | ||||
| 				if handler.Configuration.Notify.Enabled { | ||||
| 					log.Print("Sending notification to:", handler.Configuration.Notify.SendTo) | ||||
| 				// Send notification | ||||
| 				if err := godns.SendNotify(handler.Configuration, fmt.Sprintf("%s.%s", subDomain, domain.DomainName), currentIP); err != nil { | ||||
| 					log.Println("Failed to send notification") | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		} | ||||
| 		// Sleep with interval | ||||
| 		log.Printf("Going to sleep, will start next checking in %d seconds...\r\n", handler.Configuration.Interval) | ||||
| 		time.Sleep(time.Second * time.Duration(handler.Configuration.Interval)) | ||||
|  | ||||
| @ -57,15 +57,12 @@ func (handler *Handler) DomainLoop(domain *godns.Domain, panicChan chan<- godns. | ||||
| 				log.Printf("%s.%s Start to update record IP...\n", subDomain, domain.DomainName) | ||||
| 				handler.UpdateIP(domain.DomainName, subDomain, currentIP) | ||||
| 
 | ||||
| 				// Send mail notification if notify is enabled | ||||
| 				if handler.Configuration.Notify.Enabled { | ||||
| 					log.Print("Sending notification to:", handler.Configuration.Notify.SendTo) | ||||
| 				// Send notification | ||||
| 				if err := godns.SendNotify(handler.Configuration, fmt.Sprintf("%s.%s", subDomain, domain.DomainName), currentIP); err != nil { | ||||
| 					log.Println("Failed to send notification") | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		} | ||||
| 		// Sleep with interval | ||||
| 		log.Printf("Going to sleep, will start next checking in %d seconds...\r\n", handler.Configuration.Interval) | ||||
| 		time.Sleep(time.Second * time.Duration(handler.Configuration.Interval)) | ||||
|  | ||||
							
								
								
									
										16
									
								
								settings.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								settings.go
									
									
									
									
									
								
							| @ -12,8 +12,16 @@ type Domain struct { | ||||
| 	SubDomains []string `json:"sub_domains"` | ||||
| } | ||||
| 
 | ||||
| // Notify struct for telegram notification | ||||
| type TelegramNotify struct { | ||||
| 	Enabled      bool   `json:"enabled"` | ||||
| 	BotApiKey    string `json:"bot_api_key"` | ||||
| 	ChatId       string `json:"chat_id"` | ||||
| 	MsgTemplate  string `json:"message_template"` | ||||
| } | ||||
| 
 | ||||
| // Notify struct for SMTP notification | ||||
| type Notify struct { | ||||
| type MailNotify struct { | ||||
| 	Enabled      bool   `json:"enabled"` | ||||
| 	SMTPServer   string `json:"smtp_server"` | ||||
| 	SMTPUsername string `json:"smtp_username"` | ||||
| @ -22,6 +30,12 @@ type Notify struct { | ||||
| 	SendTo       string `json:"send_to"` | ||||
| } | ||||
| 
 | ||||
| // Notify struct | ||||
| type Notify struct { | ||||
| 	Telegram    TelegramNotify `json:"telegram"` | ||||
| 	Mail        MailNotify `json:"mail"` | ||||
| } | ||||
| 
 | ||||
| // Settings struct | ||||
| type Settings struct { | ||||
| 	Provider    string   `json:"provider"` | ||||
|  | ||||
							
								
								
									
										96
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								utils.go
									
									
									
									
									
								
							| @ -2,7 +2,9 @@ package godns | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"html/template" | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| @ -234,30 +236,108 @@ func CheckSettings(config *Settings) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SendNotify sends notify if IP is changed | ||||
| func SendTelegramNotify(configuration *Settings, domain, currentIP string) error { | ||||
| 	if ! configuration.Notify.Telegram.Enabled { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if configuration.Notify.Telegram.BotApiKey == "" { | ||||
| 		return errors.New("bot api key cannot be empty") | ||||
| 	} | ||||
| 
 | ||||
| 	if configuration.Notify.Telegram.ChatId == "" { | ||||
| 		return errors.New("chat id cannot be empty") | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	client := GetHttpClient(configuration) | ||||
| 	tpl := configuration.Notify.Telegram.MsgTemplate | ||||
| 	if tpl == "" { | ||||
| 		tpl = "_Your IP address is changed to_%0A%0A*{{ .CurrentIP }}*%0A%0ADomain *{{ .Domain }}* is updated" | ||||
| 	} | ||||
| 
 | ||||
| 	msg := buildTemplate(currentIP, domain, tpl) | ||||
| 	url := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s&parse_mode=Markdown&text=%s", | ||||
| 			configuration.Notify.Telegram.BotApiKey, | ||||
| 			configuration.Notify.Telegram.ChatId, | ||||
| 			msg) | ||||
| 	var response *http.Response | ||||
| 	var err error | ||||
| 
 | ||||
| 	response, err = client.Get(url) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	defer response.Body.Close() | ||||
| 
 | ||||
| 	body, _ := ioutil.ReadAll(response.Body) | ||||
| 	type ResponseParameters struct { | ||||
| 		MigrateToChatID int64 `json:"migrate_to_chat_id"` // optional | ||||
| 		RetryAfter      int   `json:"retry_after"`        // optional | ||||
| 	} | ||||
| 	type APIResponse struct { | ||||
| 		Ok          bool                `json:"ok"` | ||||
| 		Result      json.RawMessage     `json:"result"` | ||||
| 		ErrorCode   int                 `json:"error_code"` | ||||
| 		Description string              `json:"description"` | ||||
| 		Parameters  *ResponseParameters `json:"parameters"` | ||||
| 	} | ||||
| 	var resp APIResponse | ||||
| 	err = json.Unmarshal([]byte(body), &resp) | ||||
| 	if err != nil { | ||||
| 		fmt.Println("error:", err) | ||||
| 		return errors.New("Failed to parse response") | ||||
| 	} | ||||
| 	if ! resp.Ok { | ||||
| 		return errors.New(resp.Description) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SendNotify sends mail notify if IP is changed | ||||
| func SendNotify(configuration *Settings, domain, currentIP string) error { | ||||
| func SendMailNotify(configuration *Settings, domain, currentIP string) error { | ||||
| 	if ! configuration.Notify.Mail.Enabled { | ||||
| 		return nil | ||||
| 	} | ||||
| 	log.Print("Sending notification to:", configuration.Notify.Mail.SendTo) | ||||
| 	m := gomail.NewMessage() | ||||
| 
 | ||||
| 	m.SetHeader("From", configuration.Notify.SMTPUsername) | ||||
| 	m.SetHeader("To", configuration.Notify.SendTo) | ||||
| 	m.SetHeader("From", configuration.Notify.Mail.SMTPUsername) | ||||
| 	m.SetHeader("To", configuration.Notify.Mail.SendTo) | ||||
| 	m.SetHeader("Subject", "GoDNS Notification") | ||||
| 	log.Println("currentIP:", currentIP) | ||||
| 	log.Println("domain:", domain) | ||||
| 	m.SetBody("text/html", buildTemplate(currentIP, domain)) | ||||
| 	m.SetBody("text/html", buildTemplate(currentIP, domain, mailTemplate)) | ||||
| 
 | ||||
| 	d := gomail.NewPlainDialer(configuration.Notify.SMTPServer, configuration.Notify.SMTPPort, configuration.Notify.SMTPUsername, configuration.Notify.SMTPPassword) | ||||
| 	d := gomail.NewPlainDialer(configuration.Notify.Mail.SMTPServer, configuration.Notify.Mail.SMTPPort, configuration.Notify.Mail.SMTPUsername, configuration.Notify.Mail.SMTPPassword) | ||||
| 
 | ||||
| 	// Send the email config by sendlist	. | ||||
| 	if err := d.DialAndSend(m); err != nil { | ||||
| 		log.Println("Send email notification with error:", err.Error()) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func buildTemplate(currentIP, domain string) string { | ||||
| // SendNotify sends notify if IP is changed | ||||
| func SendNotify(configuration *Settings, domain, currentIP string) error { | ||||
| 	err := SendTelegramNotify(configuration, domain, currentIP) | ||||
| 	if (err != nil) { | ||||
| 		log.Println("Send telegram notification with error:", err.Error()) | ||||
| 	} | ||||
| 	err = SendMailNotify(configuration, domain, currentIP) | ||||
| 	if (err != nil) { | ||||
| 		log.Println("Send email notification with error:", err.Error()) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func buildTemplate(currentIP, domain string, tplsrc string) string { | ||||
| 	t := template.New("notification template") | ||||
| 	if _, err := t.Parse(mailTemplate); err != nil { | ||||
| 	if _, err := t.Parse(tplsrc); err != nil { | ||||
| 		log.Println("Failed to parse template") | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user