Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 30 additions & 17 deletions parser/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ var deviceTypes = map[string]int{
`peripheral`: DEVICE_TYPE_PERIPHERAL,
}

var deviceTypeIds = make(map[int]string, len(deviceTypes))

func init() {
for k, v := range deviceTypes {
deviceTypeIds[v] = k
}
if len(deviceTypeIds) != len(deviceTypes) {
panic("duplicate device type")
}
}

// Known device brands
// Note: Before using a new brand in on of the regex files, it needs to be added here
var deviceBrands = map[string]string{
Expand Down Expand Up @@ -2138,6 +2149,17 @@ var deviceBrands = map[string]string{
`XX`: `Unknown`,
}

var deviceBrandIds = make(map[string]string, len(deviceBrands))

func init() {
for k, v := range deviceBrands {
deviceBrandIds[v] = k
}
if len(deviceBrandIds) != len(deviceBrandIds) {
panic("duplicate device brands")
}
}

// Returns names of all available device types
func GetAvailableDeviceTypeNames() []string {
keys := make([]string, 0, len(deviceTypes))
Expand All @@ -2149,12 +2171,8 @@ func GetAvailableDeviceTypeNames() []string {

// Returns the name of the given device type
func GetDeviceName(deviceType int) string {
for k, v := range deviceTypes {
if v == deviceType {
return k
}
}
return ""
deviceName := deviceTypeIds[deviceType]
return deviceName
}

func GetDeviceType(deviceName string) int {
Expand All @@ -2171,19 +2189,14 @@ func GetFullName(brandId string) string {
}

func GetShortName(name string) string {
for k, v := range deviceBrands {
if v == name {
return k
}
shortName, ok := deviceBrandIds[name]
if !ok {
shortName = name
}
return name
return shortName
}

func FindBrand(key string) string {
for k, v := range deviceBrands {
if v == key {
return k
}
}
return ""
brand := deviceBrandIds[key]
return brand
}
38 changes: 26 additions & 12 deletions parser/device/device_parser.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package device

import (
"sort"
"cmp"
"slices"
"strings"

. "github.com/slipros/devicedetector/parser"
Expand Down Expand Up @@ -29,29 +30,46 @@ type Model struct {

type DeviceReg struct {
Regular `yaml:",inline" json:",inline"`
Brand string `yaml:"brand" json:"brand"`
Model string `yaml:"model" json:"model"`
Device string `yaml:"device" json:"device"`
Models []*Model `yaml:"models" json:"models"`
}

type DeviceParserAbstract struct {
Regexes map[string]*DeviceReg
Regexes []*DeviceReg
overAllMatch Regular
}

func (d *DeviceParserAbstract) Load(file string) error {
var v map[string]*DeviceReg
var unknownDeviceReg *DeviceReg
err := ReadYamlFile(file, &v)
if err != nil {
return err
}
for _, item := range v {
for brand, item := range v {
item.Brand = brand
item.Compile()
for _, m := range item.Models {
m.Compile()
}
if brand != UnknownBrand {
d.Regexes = append(d.Regexes, item)
} else {
unknownDeviceReg = item
}
}
// Sort regexes DeviceReg array
brandCmp := func(a, b *DeviceReg) int {
return cmp.Compare(a.Brand, b.Brand)
}
slices.SortFunc(d.Regexes, brandCmp)

// Finally append the catch-all unknown device if it exists.
if unknownDeviceReg != nil {
d.Regexes = append(d.Regexes, unknownDeviceReg)
}
d.Regexes = v
return nil
}

Expand All @@ -61,16 +79,11 @@ func (d *DeviceParserAbstract) PreMatch(ua string) bool {
if count == 0 {
return false
}
sortKeys := make([]string, 0, count)
for k, _ := range d.Regexes {
sortKeys = append(sortKeys, k)
}
sort.Strings(sortKeys)
sb := strings.Builder{}
sb.WriteString(d.Regexes[sortKeys[count-1]].Regex)
sb.WriteString(d.Regexes[count-1].Regex)
for i := count - 2; i >= 0; i-- {
sb.WriteString("|")
sb.WriteString(d.Regexes[sortKeys[i]].Regex)
sb.WriteString(d.Regexes[i].Regex)
}
d.overAllMatch.Regex = sb.String()
d.overAllMatch.Compile()
Expand All @@ -83,7 +96,8 @@ func (d *DeviceParserAbstract) Parse(ua string) *DeviceMatchResult {
var regex *DeviceReg
var brand string
var matches []string
for brand, regex = range d.Regexes {
for _, regex = range d.Regexes {
brand = regex.Brand
matches = regex.MatchUserAgent(ua)
if len(matches) > 0 {
break
Expand Down