commit 912f9fd0ad210e5fd22cd3cb640cf109e49b86dd
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2026-03-07T14:16:14Z |
| subject | Refactoring codes for more tg message types |
commit 912f9fd0ad210e5fd22cd3cb640cf109e49b86dd
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2026-03-07T14:16:14Z
Refactoring codes for more tg message types
---
adaptors/tg/botsend.go | 56 +++++++
datasources/cjlookup/CChar.go | 6 +-
datasources/cjlookup/QueryResult.go | 11 +-
datasources/cjlookup/query.go | 14 +-
datasources/kmb/QueryResult.go | 319 ++++++++++++++++++------------------
datasources/kmb/RouteStop.go | 85 +++++-----
datasources/kmb/query.go | 7 +-
datasources/mtr/bus/BusStop.go | 12 +-
datasources/mtr/bus/QueryResult.go | 48 +++++-
datasources/mtr/bus/busstops.go | 2 +-
datasources/mtr/bus/query.go | 13 +-
go.mod | 2 +
go.sum | 2 +
i18n/Generics.go | 6 +-
main.go | 40 +++--
query/GeoLocation.go | 59 +++++++
query/IQueryResult.go | 5 -
query/Searchable.go | 43 +----
query/Words.go | 43 +++++
query/geo_test.go | 33 ++++
query/match_keys.go | 69 ++++++++
query/match_locations.go | 29 ++++
query/objects.go | 27 +++
query/query.go | 81 ---------
query/query_test.go | 115 ++++++-------
utils/system.go | 128 ++++++++-------
26 files changed, 777 insertions(+), 478 deletions(-)
diff --git a/adaptors/tg/botsend.go b/adaptors/tg/botsend.go
new file mode 100644
index 0000000..9885d8f
--- /dev/null
+++ b/adaptors/tg/botsend.go
@@ -0,0 +1,56 @@
+package tg
+
+import (
+ tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
+ query "github.com/tgckpg/golifehk/query"
+)
+
+func BotSendText(bot *tgbotapi.BotAPI, update *tgbotapi.Update, mesg *string) {
+ var msg tgbotapi.MessageConfig
+ msg = tgbotapi.NewMessage(update.Message.Chat.ID, *mesg)
+ msg.ParseMode = "MarkdownV2"
+
+ msg.ReplyToMessageID = update.Message.MessageID
+ bot.Send(msg)
+}
+
+func BotSend(bot *tgbotapi.BotAPI, update *tgbotapi.Update, qResult query.IQueryResult) (bool, error) {
+
+ var msg tgbotapi.MessageConfig
+ mesg, err := qResult.Message()
+
+ if err != nil {
+ // not sent, error
+ return false, err
+ }
+
+ mesgType := qResult.DataType()
+
+ switch mesgType {
+ case "IGNORE":
+ // not sent with no error tells the parent to look for other processors
+ return false, nil
+ }
+
+ msg = tgbotapi.NewMessage(update.Message.Chat.ID, mesg)
+ msg.ParseMode = "MarkdownV2"
+
+ switch mesgType {
+ case "PlainText":
+ case "Table":
+
+ button := tgbotapi.NewInlineKeyboardButtonData(
+ "Show Status", // what user sees
+ "status_cmd", // what bot receives
+ )
+
+ msg.ReplyMarkup = tgbotapi.NewInlineKeyboardMarkup(
+ tgbotapi.NewInlineKeyboardRow(button, button),
+ )
+
+ }
+
+ msg.ReplyToMessageID = update.Message.MessageID
+ bot.Send(msg)
+ return true, nil
+}
diff --git a/datasources/cjlookup/CChar.go b/datasources/cjlookup/CChar.go
index 4898051..689e76a 100644
--- a/datasources/cjlookup/CChar.go
+++ b/datasources/cjlookup/CChar.go
@@ -12,7 +12,8 @@ type CChar struct {
JyutPing *CJyutPing
DukJam *[]*DukJam
_JiDukJam *[]*CJyutPing
- query.Searchable
+ query.Words
+ query.NoGeoLocation
}
type DukJam struct {
@@ -25,7 +26,8 @@ type CJyutPing struct {
SearchKey string // Searchable key
TungJamZi *[]*CChar
tSorted bool
- query.Searchable
+ query.Words
+ query.NoGeoLocation
}
func (this *CJyutPing) Test(val string) bool {
diff --git a/datasources/cjlookup/QueryResult.go b/datasources/cjlookup/QueryResult.go
index a824bbc..16a9272 100644
--- a/datasources/cjlookup/QueryResult.go
+++ b/datasources/cjlookup/QueryResult.go
@@ -13,6 +13,9 @@ type QueryResult struct {
Lang string
Error error
Query *query.QueryObject
+
+ ResultType string
+ isConsumed bool
}
func writeCCharInfo(sb *strings.Builder, cc *CChar) {
@@ -37,14 +40,20 @@ func writeCCharInfo(sb *strings.Builder, cc *CChar) {
}
}
+func (this QueryResult) DataType() string { return this.ResultType }
+func (this QueryResult) Consumed() bool { return this.isConsumed }
+func (this QueryResult) GetTableData() [][]map[string]string { return nil }
+
func (this QueryResult) Message() (string, error) {
+ this.ResultType = "PlainText"
+
if this.Error != nil {
return "", this.Error
}
if this.Query == nil {
- panic("Query is nil")
+ return "", nil
}
sb := strings.Builder{}
diff --git a/datasources/cjlookup/query.go b/datasources/cjlookup/query.go
index d1aa5f0..19c039f 100644
--- a/datasources/cjlookup/query.go
+++ b/datasources/cjlookup/query.go
@@ -1,13 +1,16 @@
package cjlookup
import (
- "fmt"
"strings"
"github.com/tgckpg/golifehk/query"
)
-func Query(lang string, message string) query.IQueryResult {
+func Query(q query.QueryMessage) query.IQueryResult {
+
+ lang := q.Lang
+ message := q.Text
+
var qResults *query.QueryObject
var err error
var searchables *[]query.ISearchable
@@ -17,9 +20,12 @@ func Query(lang string, message string) query.IQueryResult {
// Only look up jyut ping
if !strings.HasPrefix(messageU, "JP ") {
- err = fmt.Errorf("Invalid query")
+ qr.ResultType = "IGNORE"
+ goto qrReturn
}
+ qr.isConsumed = true
+
if err != nil {
qr.Error = err
goto qrReturn
@@ -28,7 +34,7 @@ func Query(lang string, message string) query.IQueryResult {
messageU = messageU[3:]
searchables, err = getSearchables()
- qResults, err = query.Parse(messageU, searchables)
+ qResults, err = query.MatchKeys(messageU, searchables)
qr.Query = qResults
diff --git a/datasources/kmb/QueryResult.go b/datasources/kmb/QueryResult.go
index 3a9ee42..a1bdce0 100644
--- a/datasources/kmb/QueryResult.go
+++ b/datasources/kmb/QueryResult.go
@@ -1,176 +1,181 @@
package kmb
import (
- "fmt"
- "sort"
- "strings"
- "time"
+ "fmt"
+ "sort"
+ "strings"
+ "time"
- query "github.com/tgckpg/golifehk/query"
- utils "github.com/tgckpg/golifehk/utils"
+ query "github.com/tgckpg/golifehk/query"
+ utils "github.com/tgckpg/golifehk/utils"
)
type QueryResult struct {
- Schedules *map[*RouteStop] *[] *Schedule
- Lang string
- Error error
- Query *query.QueryObject
+ Schedules *map[*RouteStop]*[]*Schedule
+ Lang string
+ Error error
+ Query *query.QueryObject
+
+ isConsumed bool
}
-func writeRouteHead( sb *strings.Builder, r *RouteStop ) {
- utils.WriteMDv2Text( sb, r.RouteId )
- if r.Direction == "O" {
- sb.WriteString( "↑" )
- } else if r.Direction == "I" {
- sb.WriteString( "↓" )
- }
- if r.ServiceType != "1" {
- utils.WriteMDv2Text( sb, utils.ToPower( r.ServiceType ) )
- }
+func writeRouteHead(sb *strings.Builder, r *RouteStop) {
+ utils.WriteMDv2Text(sb, r.RouteId)
+ if r.Direction == "O" {
+ sb.WriteString("↑")
+ } else if r.Direction == "I" {
+ sb.WriteString("↓")
+ }
+ if r.ServiceType != "1" {
+ utils.WriteMDv2Text(sb, utils.ToPower(r.ServiceType))
+ }
}
-func writeShortRoute( lang *string, sb *strings.Builder, r *RouteStop ) {
+func writeShortRoute(lang *string, sb *strings.Builder, r *RouteStop) {
- if r.PrevStop() != nil {
- utils.WriteMDv2Text( sb, (*(r.PrevStop().BusStop).Name)[ *lang ] )
- sb.WriteString( " \\> " )
- }
+ if r.PrevStop() != nil {
+ utils.WriteMDv2Text(sb, (*(r.PrevStop().BusStop).Name)[*lang])
+ sb.WriteString(" \\> ")
+ }
- sb.WriteString( "*" )
- utils.WriteMDv2Text( sb, (*(r.BusStop).Name)[ *lang ] )
- sb.WriteString( "*" )
+ sb.WriteString("*")
+ utils.WriteMDv2Text(sb, (*(r.BusStop).Name)[*lang])
+ sb.WriteString("*")
- if r.NextStop() != nil {
- sb.WriteString( " \\> " )
- utils.WriteMDv2Text( sb, (*(r.NextStop().BusStop).Name)[ *lang ] )
- }
+ if r.NextStop() != nil {
+ sb.WriteString(" \\> ")
+ utils.WriteMDv2Text(sb, (*(r.NextStop().BusStop).Name)[*lang])
+ }
- sb.WriteString( "\n" )
+ sb.WriteString("\n")
}
-func ( this *QueryResult ) Message() ( string, error ) {
+func (this QueryResult) DataType() string { return "MarkdownV2" }
+func (this QueryResult) Consumed() bool { return this.isConsumed }
+func (this QueryResult) GetTableData() [][]map[string]string { return nil }
+
+func (this *QueryResult) Message() (string, error) {
- if this.Error != nil {
- return "", this.Error
- }
-
- sb := strings.Builder{}
-
- if 0 < len( *this.Query.Results ) {
-
- // Print Stop Names, then print the list of routes
- if this.Query.Key == "" {
- busStops := map[string] *BusStop{}
- for _, item := range *this.Query.Results {
- var r *RouteStop
- r = any( item ).( *RouteStop )
-
- b := r.BusStop
- if b.Routes == nil {
- continue
- }
-
- busStops[ b.BusStopId ] = b
- }
-
- for _, b := range busStops {
- utils.WriteMDv2Text( &sb, (*b.Name)[ this.Lang ] )
- sb.WriteString( "\n " )
- for _, route := range *b.Routes {
- writeRouteHead( &sb, route )
- sb.WriteString( " " )
- }
- sb.WriteString( "\n" )
- }
-
- // We got a route key
- } else {
-
- // We also got other search keys with 1 < Results
- // Get the ETA for this stop
- if 1 < len( *this.Query.SearchTerms ) {
-
- now := time.Now()
- for _, item := range *this.Query.Results {
- var r *RouteStop
- r = any( item ).( *RouteStop )
- writeRouteHead( &sb, r )
- sb.WriteString( "\n" )
- writeShortRoute( &this.Lang, &sb, r )
-
- for _, schedule := range *(*this.Schedules)[ r ] {
-
- if !schedule.ETA.IsZero() {
-
- _m := schedule.ETA.Sub( now ).Minutes()
-
- sb.WriteString( " \\* " )
- txt := "%.0f min(s)"
-
- if this.Lang == "zh-Hant" {
- txt = "%.0f 分鐘"
- }
-
- utils.WriteMDv2Text( &sb, fmt.Sprintf( txt, _m ) )
-
- if _m < 0 {
- sb.WriteString( " 走左了?" )
- }
- }
-
- if schedule.Remarks_en != "" {
- sb.WriteString( " \\*\\* " )
- switch this.Lang {
- case "en":
- utils.WriteMDv2Text( &sb, schedule.Remarks_en )
- case "zh-Hant":
- utils.WriteMDv2Text( &sb, schedule.Remarks_tc )
- }
- }
-
- sb.WriteString( "\n" )
- }
-
- sb.WriteString( "\n" )
- }
-
- // We got only the route key, proceed to list the route stops
- } else {
- // Result contains all route stops, we only need the starting one
- routes := [] *RouteStop{}
-
- for _, item := range *this.Query.Results {
- var r *RouteStop
- r = any( item ).( *RouteStop )
- if r.PrevStop() == nil {
- routes = append( routes, r )
- }
- }
-
- sort.Sort( ByRoute( routes ) )
-
- for _, r := range routes {
- writeRouteHead( &sb, r )
- sb.WriteString( "\n" )
- for {
- b := *r.BusStop
- utils.WriteMDv2Text( &sb, (*b.Name)[ this.Lang ] )
- r = r.NextStop()
- if r == nil {
- break
- }
-
- sb.WriteString( " \\> " )
- }
- sb.WriteString( "\n" )
- }
-
-
- }
- }
- } else {
- return "", fmt.Errorf( "No Results" )
- }
-
- return sb.String(), nil
+ if this.Error != nil {
+ return "", this.Error
+ }
+
+ sb := strings.Builder{}
+
+ if 0 < len(*this.Query.Results) {
+
+ // Print Stop Names, then print the list of routes
+ if this.Query.Key == "" {
+ busStops := map[string]*BusStop{}
+ for _, item := range *this.Query.Results {
+ var r *RouteStop
+ r = any(item).(*RouteStop)
+
+ b := r.BusStop
+ if b.Routes == nil {
+ continue
+ }
+
+ busStops[b.BusStopId] = b
+ }
+
+ for _, b := range busStops {
+ utils.WriteMDv2Text(&sb, (*b.Name)[this.Lang])
+ sb.WriteString("\n ")
+ for _, route := range *b.Routes {
+ writeRouteHead(&sb, route)
+ sb.WriteString(" ")
+ }
+ sb.WriteString("\n")
+ }
+
+ // We got a route key
+ } else {
+
+ // We also got other search keys with 1 < Results
+ // Get the ETA for this stop
+ if 1 < len(*this.Query.SearchTerms) {
+
+ now := time.Now()
+ for _, item := range *this.Query.Results {
+ var r *RouteStop
+ r = any(item).(*RouteStop)
+ writeRouteHead(&sb, r)
+ sb.WriteString("\n")
+ writeShortRoute(&this.Lang, &sb, r)
+
+ for _, schedule := range *(*this.Schedules)[r] {
+
+ if !schedule.ETA.IsZero() {
+
+ _m := schedule.ETA.Sub(now).Minutes()
+
+ sb.WriteString(" \\* ")
+ txt := "%.0f min(s)"
+
+ if this.Lang == "zh-Hant" {
+ txt = "%.0f 分鐘"
+ }
+
+ utils.WriteMDv2Text(&sb, fmt.Sprintf(txt, _m))
+
+ if _m < 0 {
+ sb.WriteString(" 走左了?")
+ }
+ }
+
+ if schedule.Remarks_en != "" {
+ sb.WriteString(" \\*\\* ")
+ switch this.Lang {
+ case "en":
+ utils.WriteMDv2Text(&sb, schedule.Remarks_en)
+ case "zh-Hant":
+ utils.WriteMDv2Text(&sb, schedule.Remarks_tc)
+ }
+ }
+
+ sb.WriteString("\n")
+ }
+
+ sb.WriteString("\n")
+ }
+
+ // We got only the route key, proceed to list the route stops
+ } else {
+ // Result contains all route stops, we only need the starting one
+ routes := []*RouteStop{}
+
+ for _, item := range *this.Query.Results {
+ var r *RouteStop
+ r = any(item).(*RouteStop)
+ if r.PrevStop() == nil {
+ routes = append(routes, r)
+ }
+ }
+
+ sort.Sort(ByRoute(routes))
+
+ for _, r := range routes {
+ writeRouteHead(&sb, r)
+ sb.WriteString("\n")
+ for {
+ b := *r.BusStop
+ utils.WriteMDv2Text(&sb, (*b.Name)[this.Lang])
+ r = r.NextStop()
+ if r == nil {
+ break
+ }
+
+ sb.WriteString(" \\> ")
+ }
+ sb.WriteString("\n")
+ }
+
+ }
+ }
+ } else {
+ return "", fmt.Errorf("No Results")
+ }
+
+ return sb.String(), nil
}
diff --git a/datasources/kmb/RouteStop.go b/datasources/kmb/RouteStop.go
index 3a1a1f6..d9554a4 100644
--- a/datasources/kmb/RouteStop.go
+++ b/datasources/kmb/RouteStop.go
@@ -1,65 +1,66 @@
package kmb
import (
- query "github.com/tgckpg/golifehk/query"
+ query "github.com/tgckpg/golifehk/query"
)
type RouteStop struct {
- BusStop *BusStop
- RouteId string `json:"route"`
- ServiceType string `json:"service_type"`
- Direction string `json:"bound"`
- StationSeq int `json:"seq,string"`
- StationId string `json:"stop"`
+ BusStop *BusStop
+ RouteId string `json:"route"`
+ ServiceType string `json:"service_type"`
+ Direction string `json:"bound"`
+ StationSeq int `json:"seq,string"`
+ StationId string `json:"stop"`
- RouteStops *map[int] *RouteStop
- query.Searchable
+ RouteStops *map[int]*RouteStop
+ query.Words
+ query.NoGeoLocation
}
type RouteStops struct {
- Type string `json:"type"`
- Version string `json:"version"`
- DateCreated string `json:"generated_timestamp"`
- RouteStops [] *RouteStop `json:"data"`
+ Type string `json:"type"`
+ Version string `json:"version"`
+ DateCreated string `json:"generated_timestamp"`
+ RouteStops []*RouteStop `json:"data"`
}
-func ( routeStop RouteStop ) PrevStop() *RouteStop {
- if v, hasKey := (*routeStop.RouteStops)[ routeStop.StationSeq - 1 ]; hasKey {
- return v
- }
- return nil
+func (routeStop RouteStop) PrevStop() *RouteStop {
+ if v, hasKey := (*routeStop.RouteStops)[routeStop.StationSeq-1]; hasKey {
+ return v
+ }
+ return nil
}
-func ( routeStop RouteStop ) NextStop() *RouteStop {
- if v, hasKey := (*routeStop.RouteStops)[ routeStop.StationSeq + 1 ]; hasKey {
- return v
- }
- return nil
+func (routeStop RouteStop) NextStop() *RouteStop {
+ if v, hasKey := (*routeStop.RouteStops)[routeStop.StationSeq+1]; hasKey {
+ return v
+ }
+ return nil
}
-func ( this *RouteStop ) Reload() {
+func (this *RouteStop) Reload() {
- searchData := [] *string{}
- busStop := *this.BusStop
- searchData = append( searchData, &busStop.Name_en )
- searchData = append( searchData, &busStop.Name_tc )
+ searchData := []*string{}
+ busStop := *this.BusStop
+ searchData = append(searchData, &busStop.Name_en)
+ searchData = append(searchData, &busStop.Name_tc)
- this.Key = &this.RouteId
- this.SearchData = &searchData
+ this.Key = &this.RouteId
+ this.SearchData = &searchData
}
-type ByRoute [] *RouteStop
+type ByRoute []*RouteStop
-func (a ByRoute) Len() int { return len(a) }
-func (a ByRoute) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a ByRoute) Len() int { return len(a) }
+func (a ByRoute) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByRoute) Less(i, j int) bool {
- _a := *a[i]
- _b := *a[j]
- if _a.RouteId == _b.RouteId {
- if _a.Direction == _b.Direction {
- return _a.ServiceType < _b.ServiceType
- }
- return _a.Direction < _b.Direction
- }
- return _a.RouteId < _b.RouteId
+ _a := *a[i]
+ _b := *a[j]
+ if _a.RouteId == _b.RouteId {
+ if _a.Direction == _b.Direction {
+ return _a.ServiceType < _b.ServiceType
+ }
+ return _a.Direction < _b.Direction
+ }
+ return _a.RouteId < _b.RouteId
}
diff --git a/datasources/kmb/query.go b/datasources/kmb/query.go
index 2ab81c0..c6b18d2 100644
--- a/datasources/kmb/query.go
+++ b/datasources/kmb/query.go
@@ -6,7 +6,10 @@ import (
"strings"
)
-func Query(lang string, message string) query.IQueryResult {
+func Query(q query.QueryMessage) query.IQueryResult {
+
+ lang := q.Lang
+ message := q.Text
var qo *query.QueryObject
var err error
@@ -18,7 +21,7 @@ func Query(lang string, message string) query.IQueryResult {
goto qrReturn
}
- qo, err = query.Parse(strings.ToUpper(message), routeStops)
+ qo, err = query.MatchKeys(strings.ToUpper(message), routeStops)
if err != nil {
qr.Error = err
goto qrReturn
diff --git a/datasources/mtr/bus/BusStop.go b/datasources/mtr/bus/BusStop.go
index c11fb52..d09f054 100644
--- a/datasources/mtr/bus/BusStop.go
+++ b/datasources/mtr/bus/BusStop.go
@@ -2,6 +2,7 @@ package bus
import (
i18n "github.com/tgckpg/golifehk/i18n"
+ query "github.com/tgckpg/golifehk/query"
)
type BusStop struct {
@@ -10,8 +11,6 @@ type BusStop struct {
Direction string
StationSeq int
StationId string
- Latitude float64
- Longtitude float64
Name_zh string
Name_en string
@@ -22,6 +21,7 @@ type BusStop struct {
AltRoutes *map[string]*BusStop
i18n.Generics
+ query.GeoLocation
}
func (this *BusStop) PrevStop() *BusStop {
@@ -52,6 +52,14 @@ func (this *BusStop) Reload() {
this.SearchData = &searchData
}
+func (this BusStop) Register(registers map[string]struct{}) bool {
+ if _, ok := registers[this.StationId]; ok {
+ return false
+ }
+ registers[this.StationId] = struct{}{}
+ return true
+}
+
type ByRoute []*BusStop
func (a ByRoute) Len() int { return len(a) }
diff --git a/datasources/mtr/bus/QueryResult.go b/datasources/mtr/bus/QueryResult.go
index 9371715..0434b9d 100644
--- a/datasources/mtr/bus/QueryResult.go
+++ b/datasources/mtr/bus/QueryResult.go
@@ -14,7 +14,10 @@ type QueryResult struct {
Schedules *map[*BusStop]*BusStopBuses
Lang string
Error error
+ Source *query.QueryMessage
Query *query.QueryObject
+
+ isConsumed bool
}
func writeShortRoute(lang *string, sb *strings.Builder, b *BusStop) {
@@ -35,6 +38,10 @@ func writeShortRoute(lang *string, sb *strings.Builder, b *BusStop) {
sb.WriteString("\n")
}
+func (this QueryResult) DataType() string { return "MarkdownV2" }
+func (this QueryResult) Consumed() bool { return this.isConsumed }
+func (this QueryResult) GetTableData() [][]map[string]string { return nil }
+
func (this QueryResult) Message() (string, error) {
if this.Error != nil {
@@ -56,12 +63,41 @@ func (this QueryResult) Message() (string, error) {
}
if q.Key == "" {
- sort.Sort(query.ByKey(*q.Results))
- for _, entry := range *q.Results {
- busStop := any(entry).(*BusStop)
- utils.WriteMDv2Text(&sb, busStop.RouteId)
- sb.WriteString(" ")
- writeShortRoute(&this.Lang, &sb, busStop)
+
+ loc := q.Message.Location
+ if loc != nil {
+
+ // Print nearest bus stops
+ for _, entry := range *q.Results {
+ busStop := any(entry).(*BusStop)
+
+ utils.WriteMDv2Text(&sb, fmt.Sprintf("%.2fm", busStop.Dist(loc.Lat(), loc.Lon())))
+ sb.WriteString(" ")
+ sb.WriteString(" [")
+ utils.WriteMDv2Text(&sb, busStop.RouteId)
+ d := busStop.Direction
+ if d == "O" {
+ sb.WriteString("↑")
+ } else if d == "I" {
+ sb.WriteString("↓")
+ } else {
+ sb.WriteString("\\?")
+ }
+ utils.WriteMDv2Text(&sb, (*busStop.Name)[this.Lang])
+ utils.WriteMDv2Text(&sb, busStop.RouteId)
+ utils.WriteMDv2Text(&sb, (*busStop.Name)[this.Lang])
+ sb.WriteString(")")
+ sb.WriteString("\n")
+ }
+
+ } else {
+ sort.Sort(query.ByKey(*q.Results))
+ for _, entry := range *q.Results {
+ busStop := any(entry).(*BusStop)
+ utils.WriteMDv2Text(&sb, busStop.RouteId)
+ sb.WriteString(" ")
+ writeShortRoute(&this.Lang, &sb, busStop)
+ }
}
} else if 1 == len(*q.SearchTerms) {
diff --git a/datasources/mtr/bus/busstops.go b/datasources/mtr/bus/busstops.go
index da47e13..832e057 100644
--- a/datasources/mtr/bus/busstops.go
+++ b/datasources/mtr/bus/busstops.go
@@ -50,7 +50,7 @@ func readBusStopData(r io.Reader) (*map[string]*BusStop, error) {
entry.Latitude = v
case "STATION_LONGITUDE":
v, _ := strconv.ParseFloat(value, 64)
- entry.Longtitude = v
+ entry.Longitude = v
case "STATION_NAME_CHI":
entry.Name_zh = value
case "STATION_NAME_ENG":
diff --git a/datasources/mtr/bus/query.go b/datasources/mtr/bus/query.go
index 5ce3e42..6778e6c 100644
--- a/datasources/mtr/bus/query.go
+++ b/datasources/mtr/bus/query.go
@@ -6,7 +6,9 @@ import (
query "github.com/tgckpg/golifehk/query"
)
-func Query(lang string, message string) query.IQueryResult {
+func Query(q query.QueryMessage) query.IQueryResult {
+
+ lang := q.Lang
var qBusStops *query.QueryObject
var err error
@@ -18,7 +20,14 @@ func Query(lang string, message string) query.IQueryResult {
goto qrReturn
}
- qBusStops, err = query.Parse(strings.ToUpper(message), busStops)
+ if q.Text != "" {
+ qBusStops, err = query.MatchKeys(strings.ToUpper(q.Text), busStops)
+ } else if q.Location != nil {
+ qBusStops, err = query.MatchNearest(*q.Location, busStops, 100, 3)
+ }
+
+ qBusStops.Message = &q
+
if err != nil {
qr.Error = err
goto qrReturn
diff --git a/go.mod b/go.mod
index 8406537..4c8ba31 100644
--- a/go.mod
+++ b/go.mod
@@ -7,3 +7,5 @@ require (
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa
golang.org/x/text v0.34.0
)
+
+require github.com/tidwall/geodesic v1.52.4 // indirect
diff --git a/go.sum b/go.sum
index 6b356b9..49f8cdd 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,7 @@
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc=
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8=
+github.com/tidwall/geodesic v1.52.4 h1:nT9cvYziVbmqFMDuvJzCJKvBJ9wFx0gRwvVrt86fpXg=
+github.com/tidwall/geodesic v1.52.4/go.mod h1:SNL5vSG4X+o0ExTya69PX7/ZQ2SAvmjAxI+o5ZGJsxs=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
diff --git a/i18n/Generics.go b/i18n/Generics.go
index ab9deb3..643d19b 100644
--- a/i18n/Generics.go
+++ b/i18n/Generics.go
@@ -1,10 +1,10 @@
package i18n
import (
- query "github.com/tgckpg/golifehk/query"
+ query "github.com/tgckpg/golifehk/query"
)
type Generics struct {
- Name *map[string] string
- query.Searchable
+ Name *map[string]string
+ query.Words
}
diff --git a/main.go b/main.go
index 52f5814..2bf2ba7 100644
--- a/main.go
+++ b/main.go
@@ -6,6 +6,7 @@ import (
"os"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
+ tgadaptor "github.com/tgckpg/golifehk/adaptors/tg"
cjlookup "github.com/tgckpg/golifehk/datasources/cjlookup"
kmb "github.com/tgckpg/golifehk/datasources/kmb"
mtrbus "github.com/tgckpg/golifehk/datasources/mtr/bus"
@@ -13,15 +14,6 @@ import (
utils "github.com/tgckpg/golifehk/utils"
)
-func botsend(bot *tgbotapi.BotAPI, update *tgbotapi.Update, mesg *string) {
- var msg tgbotapi.MessageConfig
- msg = tgbotapi.NewMessage(update.Message.Chat.ID, *mesg)
- msg.ParseMode = "MarkdownV2"
-
- msg.ReplyToMessageID = update.Message.MessageID
- bot.Send(msg)
-}
-
func main() {
bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_API_TOKEN"))
if err != nil {
@@ -48,12 +40,12 @@ func main() {
mesg, processed := utils.SystemControl(update.Message)
if processed {
if mesg != "" {
- botsend(bot, &update, &mesg)
+ tgadaptor.BotSendText(bot, &update, &mesg)
}
continue
}
- f_queries := []func(string, string) query.IQueryResult{
+ f_queries := []func(query.QueryMessage) query.IQueryResult{
cjlookup.Query,
mtrbus.Query,
kmb.Query,
@@ -61,21 +53,35 @@ func main() {
var f_sent bool = false
var f_err error = nil
+
+ tgMesg := update.Message
+ q := query.QueryMessage{Lang: "zh-Hant", Text: tgMesg.Text}
+
+ if tgMesg.Location != nil {
+ q.Location = &query.GeoLocation{tgMesg.Location.Latitude, tgMesg.Location.Longitude}
+ }
+
for _, Query := range f_queries {
- var err error
- mesg, err = Query("zh-Hant", update.Message.Text).Message()
- if err == nil {
+ qResult := Query(q)
+ sent, err := tgadaptor.BotSend(bot, &update, qResult)
+
+ if sent {
f_sent = true
- botsend(bot, &update, &mesg)
- } else if f_err == nil {
+ }
+
+ if err != nil {
f_err = err
}
+
+ if qResult.Consumed() {
+ break
+ }
}
if !isGroup && !f_sent && f_err != nil {
mesg := utils.MDv2Text(fmt.Sprintf("%s", f_err))
- botsend(bot, &update, &mesg)
+ tgadaptor.BotSendText(bot, &update, &mesg)
}
}
}
diff --git a/query/GeoLocation.go b/query/GeoLocation.go
new file mode 100644
index 0000000..db8f654
--- /dev/null
+++ b/query/GeoLocation.go
@@ -0,0 +1,59 @@
+package query
+
+import (
+ "github.com/tidwall/geodesic"
+ "sort"
+)
+
+type GeoLocation struct {
+ Latitude float64
+ Longitude float64
+}
+
+func (b GeoLocation) HasGeoLocation() bool { return true }
+
+func (b GeoLocation) Lat() float64 { return b.Latitude }
+func (b GeoLocation) Lon() float64 { return b.Longitude }
+
+func (b GeoLocation) Dist(lat float64, lon float64) float64 {
+ var dist float64
+ geodesic.WGS84.Inverse(
+ lat, lon,
+ b.Latitude, b.Longitude,
+ &dist, nil, nil,
+ )
+ return dist
+}
+
+type NoGeoLocation struct{}
+
+func (b NoGeoLocation) HasGeoLocation() bool { return false }
+func (b NoGeoLocation) Lat() float64 { return 0 }
+func (b NoGeoLocation) Lon() float64 { return 0 }
+func (b NoGeoLocation) Dist(lat, lon float64) float64 { return 0 }
+func (b NoGeoLocation) Register(map[string]struct{}) bool {
+ return false
+}
+
+type GeoLocations []ISearchable
+
+func (m GeoLocations) SortByNearest(p GeoLocation) {
+ sort.Slice(m, func(i, j int) bool {
+ return m[i].Dist(p.Lat(), p.Lon()) < m[j].Dist(p.Lat(), p.Lon())
+ })
+}
+
+func (b GeoLocation) Register(map[string]struct{}) bool {
+ return false
+}
+
+func (m GeoLocations) Clean() *GeoLocations {
+ registers := map[string]struct{}{}
+ items := &GeoLocations{}
+ for _, item := range m {
+ if item.HasGeoLocation() && item.Register(registers) {
+ *items = append(*items, item)
+ }
+ }
+ return items
+}
diff --git a/query/IQueryResult.go b/query/IQueryResult.go
deleted file mode 100644
index 1b30c8e..0000000
--- a/query/IQueryResult.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package query
-
-type IQueryResult interface {
- Message() ( string, error )
-}
diff --git a/query/Searchable.go b/query/Searchable.go
index 6706ba8..c72550c 100644
--- a/query/Searchable.go
+++ b/query/Searchable.go
@@ -1,40 +1,15 @@
package query
-import (
- "strings"
-)
-
type ISearchable interface {
- Test( string ) bool
- GetKey() *string
-}
-
-type Searchable struct {
- Key *string
- SearchData *[] *string
-}
-
-func ( this *Searchable ) Test( val string ) bool {
+ HasWords() bool
+ Test(string) bool
+ GetKey() *string
- data := this.SearchData
- if data == nil {
- return false
- }
+ HasGeoLocation() bool
+ Lat() float64
+ Lon() float64
+ Dist(lat float64, lon float64) float64
- for _, v := range *data {
- if strings.Contains( *v, val ) {
- return true
- }
- }
- return false
+ // Clean() filtering
+ Register(map[string]struct{}) bool
}
-
-func ( this *Searchable ) GetKey() *string {
- return this.Key
-}
-
-type ByKey [] ISearchable
-
-func (a ByKey) Len() int { return len(a) }
-func (a ByKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a ByKey) Less(i, j int) bool { return *a[i].GetKey() < *a[j].GetKey() }
diff --git a/query/Words.go b/query/Words.go
new file mode 100644
index 0000000..bc5c12f
--- /dev/null
+++ b/query/Words.go
@@ -0,0 +1,43 @@
+package query
+
+import (
+ "strings"
+)
+
+type Words struct {
+ Key *string
+ SearchData *[]*string
+}
+
+func (this *Words) HasWords() bool { return true }
+
+func (this *Words) Test(val string) bool {
+
+ data := this.SearchData
+ if data == nil {
+ return false
+ }
+
+ for _, v := range *data {
+ if strings.Contains(*v, val) {
+ return true
+ }
+ }
+ return false
+}
+
+func (this *Words) GetKey() *string {
+ return this.Key
+}
+
+type ByKey []ISearchable
+
+func (a ByKey) Len() int { return len(a) }
+func (a ByKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a ByKey) Less(i, j int) bool { return *a[i].GetKey() < *a[j].GetKey() }
+
+type NoWords struct{}
+
+func (this NoWords) HasWords() bool { return false }
+func (this NoWords) Test(val string) bool { return false }
+func (this NoWords) GetKey() *string { return nil }
diff --git a/query/geo_test.go b/query/geo_test.go
new file mode 100644
index 0000000..8c159fd
--- /dev/null
+++ b/query/geo_test.go
@@ -0,0 +1,33 @@
+package query
+
+import (
+ "fmt"
+ "testing"
+)
+
+type City struct {
+ Name string
+ NoWords
+ GeoLocation
+}
+
+func TestGeo(t *testing.T) {
+
+ B := GeoLocations{
+ City{Name: "Osaka", GeoLocation: GeoLocation{34.6937, 135.5023}},
+ City{Name: "Nagoya", GeoLocation: GeoLocation{35.1815, 136.9066}},
+ City{Name: "Sapporo", GeoLocation: GeoLocation{43.0618, 141.3545}},
+ City{Name: "Yokohama", GeoLocation: GeoLocation{35.4437, 139.6380}},
+ }
+
+ // Reference point A (Tokyo)
+ A := GeoLocation{35.6895, 139.6917}
+
+ // Sort by distance
+ B.SortByNearest(A)
+
+ // Print result
+ for _, loc := range B {
+ fmt.Printf("%s: %.2f km\n", loc.(City).Name, loc.Dist(A.Lat(), A.Lon())/1000)
+ }
+}
diff --git a/query/match_keys.go b/query/match_keys.go
new file mode 100644
index 0000000..7c5af38
--- /dev/null
+++ b/query/match_keys.go
@@ -0,0 +1,69 @@
+package query
+
+import (
+ "fmt"
+ "strings"
+)
+
+func MatchKeys(line string, entries *[]ISearchable) (*QueryObject, error) {
+
+ var Key string = ""
+
+ // Sanitize and assume properties for each of the keywords
+ terms := []*QTerm{}
+ for _, val := range strings.Split(line, " ") {
+
+ if val == "" {
+ continue
+ }
+
+ term := QTerm{
+ Org: val,
+ Value: strings.Trim(val, " "),
+ }
+ terms = append(terms, &term)
+ }
+
+lookForKey:
+ for _, term := range terms {
+ for _, entry := range *entries {
+ if term.Value == *entry.GetKey() {
+ Key = term.Value
+ term.IsKey = true
+ break lookForKey
+ }
+ }
+ }
+
+ matches := []ISearchable{}
+
+ if Key != "" && len(terms) == 1 {
+ for _, entry := range *entries {
+ if Key == *entry.GetKey() {
+ matches = append(matches, entry)
+ }
+ }
+ return &QueryObject{Key: Key, Results: &matches, SearchTerms: &terms}, nil
+ } else if 0 < len(terms) {
+ for _, entry := range *entries {
+ anyFailed := false
+ for _, term := range terms {
+ if term.IsKey {
+ continue
+ }
+
+ if !((Key == "" || Key == *entry.GetKey()) && entry.Test(term.Value)) {
+ anyFailed = true
+ break
+ }
+ }
+
+ if !anyFailed {
+ matches = append(matches, entry)
+ }
+ }
+ return &QueryObject{Key: Key, Results: &matches, SearchTerms: &terms}, nil
+ }
+
+ return nil, fmt.Errorf("Cannot parse: %s", line)
+}
diff --git a/query/match_locations.go b/query/match_locations.go
new file mode 100644
index 0000000..7fe39f0
--- /dev/null
+++ b/query/match_locations.go
@@ -0,0 +1,29 @@
+package query
+
+import (
+ "fmt"
+)
+
+func MatchNearest(p GeoLocation, entries *[]ISearchable, dist float64, limit int) (*QueryObject, error) {
+
+ terms := []*QTerm{
+ {
+ Org: fmt.Sprintf("%f, %f", p.Lat(), p.Lon()),
+ Value: "",
+ },
+ }
+
+ var locs *GeoLocations
+
+ locs = GeoLocations(*entries).Clean()
+ locs.SortByNearest(p)
+
+ matches := []ISearchable{}
+ for i, loc := range *locs {
+ if i < limit {
+ matches = append(matches, loc)
+ }
+ }
+
+ return &QueryObject{Key: "", Results: &matches, SearchTerms: &terms}, nil
+}
diff --git a/query/objects.go b/query/objects.go
new file mode 100644
index 0000000..bcbe66a
--- /dev/null
+++ b/query/objects.go
@@ -0,0 +1,27 @@
+package query
+
+type QTerm struct {
+ Org string
+ Value string
+ IsKey bool
+}
+
+type QueryMessage struct {
+ Lang string
+ Text string
+ Location *GeoLocation
+}
+
+type QueryObject struct {
+ Key string
+ Message *QueryMessage
+ SearchTerms *[]*QTerm
+ Results *[]ISearchable
+}
+
+type IQueryResult interface {
+ Message() (string, error)
+ DataType() string
+ GetTableData() [][]map[string]string
+ Consumed() bool
+}
diff --git a/query/query.go b/query/query.go
deleted file mode 100644
index 640744b..0000000
--- a/query/query.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package query
-
-import (
- "fmt"
- "strings"
-)
-
-type QTerm struct {
- Org string
- Value string
- IsKey bool
-}
-
-type QueryObject struct {
- Key string
- SearchTerms *[] *QTerm
- Results *[] ISearchable
-}
-
-func Parse( line string, entries *[] ISearchable ) ( *QueryObject, error ) {
-
- var Key string = ""
-
- // Sanitize and assume properties for each of the keywords
- terms := [] *QTerm{}
- for _, val := range strings.Split( line, " " ) {
-
- if val == "" {
- continue
- }
-
- term := QTerm{
- Org: val,
- Value: strings.Trim( val, " " ),
- }
- terms = append( terms, &term )
- }
-
- lookForKey:
- for _, term := range terms {
- for _, entry := range *entries {
- if term.Value == *entry.GetKey() {
- Key = term.Value
- term.IsKey = true
- break lookForKey
- }
- }
- }
-
- matches := [] ISearchable{}
-
- if Key != "" && len( terms ) == 1 {
- for _, entry := range *entries {
- if Key == *entry.GetKey() {
- matches = append( matches, entry )
- }
- }
- return &QueryObject{ Key: Key, Results: &matches, SearchTerms: &terms }, nil
- } else if 0 < len( terms ) {
- for _, entry := range *entries {
- anyFailed := false
- for _, term := range terms {
- if term.IsKey {
- continue
- }
-
- if !( ( Key == "" || Key == *entry.GetKey() ) && entry.Test( term.Value ) ) {
- anyFailed = true
- break
- }
- }
-
- if !anyFailed {
- matches = append( matches, entry )
- }
- }
- return &QueryObject{ Key: Key, Results: &matches, SearchTerms: &terms }, nil
- }
-
- return nil, fmt.Errorf( "Cannot parse: %s", line )
-}
diff --git a/query/query_test.go b/query/query_test.go
index 56c19be..df2c853 100644
--- a/query/query_test.go
+++ b/query/query_test.go
@@ -5,75 +5,76 @@ import (
)
type TestItem struct {
- Searchable
+ Words
+ NoGeoLocation
}
-func TestQuery( t *testing.T ) {
- testItems := [] ISearchable{}
+func TestQuery(t *testing.T) {
+ testItems := []ISearchable{}
- s1234 := "1234"
- sApple := "Apple"
- s0000 := "0000"
+ s1234 := "1234"
+ sApple := "Apple"
+ s0000 := "0000"
- sDat0 := "Dat0"
- data0 := [] *string{}
- data0 = append( data0, &s1234 )
- data0 = append( data0, &sApple )
- t0 := TestItem{}
- t0.Key = &sDat0
- t0.SearchData = &data0
- testItems = append( testItems, &t0 )
+ sDat0 := "Dat0"
+ data0 := []*string{}
+ data0 = append(data0, &s1234)
+ data0 = append(data0, &sApple)
+ t0 := TestItem{}
+ t0.Key = &sDat0
+ t0.SearchData = &data0
+ testItems = append(testItems, &t0)
- sDat1 := "Dat1"
- data1 := [] *string{}
- data1 = append( data1, &s0000 )
- data1 = append( data1, &sApple )
- t1 := TestItem{}
- t1.Key = &sDat1
- t1.SearchData = &data1
- testItems = append( testItems, &t1 )
+ sDat1 := "Dat1"
+ data1 := []*string{}
+ data1 = append(data1, &s0000)
+ data1 = append(data1, &sApple)
+ t1 := TestItem{}
+ t1.Key = &sDat1
+ t1.SearchData = &data1
+ testItems = append(testItems, &t1)
- sDat2 := "Dat2"
- data2 := [] *string{}
- data2 = append( data2, &sDat0 )
- t2 := TestItem{}
- t2.Key = &sDat2
- t2.SearchData = &data2
- testItems = append( testItems, &t2 )
+ sDat2 := "Dat2"
+ data2 := []*string{}
+ data2 = append(data2, &sDat0)
+ t2 := TestItem{}
+ t2.Key = &sDat2
+ t2.SearchData = &data2
+ testItems = append(testItems, &t2)
- qo, err := Parse( "Apple", &testItems )
- if err != nil {
- t.Error( err )
- }
+ qo, err := MatchKeys("Apple", &testItems)
+ if err != nil {
+ t.Error(err)
+ }
- if len(*qo.Results) != 2 {
- t.Error( "Expected 2 results when searching for \"Apple\"" )
- }
+ if len(*qo.Results) != 2 {
+ t.Error("Expected 2 results when searching for \"Apple\"")
+ }
- qo, err = Parse( "0000", &testItems )
- if err != nil {
- t.Error( err )
- }
+ qo, err = MatchKeys("0000", &testItems)
+ if err != nil {
+ t.Error(err)
+ }
- if len(*qo.Results) != 1 {
- t.Error( "Expected 1 results when searching for \"0000\"" )
- }
+ if len(*qo.Results) != 1 {
+ t.Error("Expected 1 results when searching for \"0000\"")
+ }
- qo, err = Parse( "Dat0", &testItems )
- if err != nil {
- t.Error( err )
- }
+ qo, err = MatchKeys("Dat0", &testItems)
+ if err != nil {
+ t.Error(err)
+ }
- if len(*qo.Results) != 1 {
- t.Error( "Expected 1 results when searching for \"Dat0\"" )
- }
+ if len(*qo.Results) != 1 {
+ t.Error("Expected 1 results when searching for \"Dat0\"")
+ }
- qo, err = Parse( "Dat2 Dat0", &testItems )
- if err != nil {
- t.Error( err )
- }
+ qo, err = MatchKeys("Dat2 Dat0", &testItems)
+ if err != nil {
+ t.Error(err)
+ }
- if len(*qo.Results) != 1 {
- t.Error( "Expected 1 results when searching for \"Dat2 Dat0\"" )
- }
+ if len(*qo.Results) != 1 {
+ t.Error("Expected 1 results when searching for \"Dat2 Dat0\"")
+ }
}
diff --git a/utils/system.go b/utils/system.go
index a76cc75..73e4642 100644
--- a/utils/system.go
+++ b/utils/system.go
@@ -1,96 +1,100 @@
package utils
import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "log"
- "path/filepath"
- "strings"
- "time"
- tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
+ "bytes"
+ "encoding/json"
+ "fmt"
+ tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
+ "io"
+ "log"
+ "path/filepath"
+ "strings"
+ "time"
)
-var JSON_SETTINGS string = filepath.Join( WORKDIR, "settings.json" )
+var JSON_SETTINGS string = filepath.Join(WORKDIR, "settings.json")
-var settingsTime = time.Unix( 0, 0 )
+var settingsTime = time.Unix(0, 0)
type SysSettings struct {
- IgnoredChats map[int64] bool `json:"IgnoredChats"`
+ IgnoredChats map[int64]bool `json:"IgnoredChats"`
}
-var Settings = SysSettings{ IgnoredChats: map[int64] bool{} }
+var Settings = SysSettings{IgnoredChats: map[int64]bool{}}
func rwSettings() {
- buff, err := ChangedStream( JSON_SETTINGS, writeSettings, settingsTime )
- if err != nil {
- log.Panic( err )
- return
- }
+ buff, err := ChangedStream(JSON_SETTINGS, writeSettings, settingsTime)
+ if err != nil {
+ log.Panic(err)
+ return
+ }
- conf := SysSettings{}
- err = json.Unmarshal( buff.Bytes(), &conf )
- if err != nil {
- log.Panic( err )
- return
- }
+ conf := SysSettings{}
+ err = json.Unmarshal(buff.Bytes(), &conf)
+ if err != nil {
+ log.Panic(err)
+ return
+ }
- Settings = conf
+ Settings = conf
}
-func writeSettings() ( io.Reader, error ) {
- b, err := json.Marshal( Settings )
- if err != nil {
- return nil, err
- }
- return bytes.NewBuffer( b ), nil
+func writeSettings() (io.Reader, error) {
+ b, err := json.Marshal(Settings)
+ if err != nil {
+ return nil, err
+ }
+ return bytes.NewBuffer(b), nil
}
-func SystemControl( tgMesg *tgbotapi.Message ) ( string, bool ) {
+func SystemControl(tgMesg *tgbotapi.Message) (string, bool) {
- rwSettings()
+ rwSettings()
- processed := false
- mesg := ""
+ processed := false
+ mesg := ""
+
+ if tgMesg.Text == "" {
+ return "", false
+ }
- if tgMesg.Text[0] == '/' {
- processed = true
- }
+ if tgMesg.Text[0] == '/' {
+ processed = true
+ }
- chatId := tgMesg.Chat.ID
+ chatId := tgMesg.Chat.ID
- if Settings.IgnoredChats == nil {
- Settings.IgnoredChats = map[int64] bool{}
- }
+ if Settings.IgnoredChats == nil {
+ Settings.IgnoredChats = map[int64]bool{}
+ }
- if strings.Contains( tgMesg.Text, "/golifehk disable" ) {
- mesg = fmt.Sprintf( "OK" )
- Settings.IgnoredChats[ chatId ] = true
- processed = true
- }
+ if strings.Contains(tgMesg.Text, "/golifehk disable") {
+ mesg = fmt.Sprintf("OK")
+ Settings.IgnoredChats[chatId] = true
+ processed = true
+ }
- if strings.Contains( tgMesg.Text, "/golifehk enable" ) {
- mesg = fmt.Sprintf( "OK" )
- Settings.IgnoredChats[ chatId ] = false
- processed = true
- }
+ if strings.Contains(tgMesg.Text, "/golifehk enable") {
+ mesg = fmt.Sprintf("OK")
+ Settings.IgnoredChats[chatId] = false
+ processed = true
+ }
- if processed {
- settingsTime = time.Now()
- rwSettings()
- }
+ if processed {
+ settingsTime = time.Now()
+ rwSettings()
+ }
- //// Begin processing settings
+ //// Begin processing settings
- // ignore chats if enabled
- if ignore, ok := Settings.IgnoredChats[ chatId ]; ok {
- processed = processed || ignore;
+ // ignore chats if enabled
+ if ignore, ok := Settings.IgnoredChats[chatId]; ok {
+ processed = processed || ignore
} else {
// default ignore
- processed = true;
+ processed = true
}
- return mesg, processed
+ return mesg, processed
}