Beispiel #1
0
func main() {
	var (
		device, apiServer, sqlitePath, sqliteFile, sqliteTablesDefinitionPath string
		apiPort                                                               int
	)

	flag.StringVar(&device, "device", scanner.SCANNER_DEVICE, fmt.Sprintf("The '/dev/input/event' device associated with your scanner (defaults to '%s')", scanner.SCANNER_DEVICE))
	flag.StringVar(&apiServer, "apiHost", apiServerHost, fmt.Sprintf("The hostname or IP address of the API server (defaults to '%s')", apiServerHost))
	flag.IntVar(&apiPort, "apiPort", apiServerPort, fmt.Sprintf("The API server port (defaults to '%d')", apiServerPort))
	flag.StringVar(&sqlitePath, "sqlitePath", database.SQLITE_PATH, fmt.Sprintf("Path to the sqlite file (defaults to '%s')", database.SQLITE_PATH))
	flag.StringVar(&sqliteFile, "sqliteFile", database.SQLITE_FILE, fmt.Sprintf("The sqlite database file (defaults to '%s')", database.SQLITE_FILE))
	flag.StringVar(&sqliteTablesDefinitionPath, "sqliteTables", "", fmt.Sprintf("Path to the sqlite database definitions file, %s, (use only if creating the client db for the first time)", database.TABLE_SQL_DEFINITIONS))
	flag.Parse()

	if len(sqliteTablesDefinitionPath) > 0 {
		// this is a request to create the client db for the first time
		initDb, initErr := database.InitializeDB(database.ConnCoordinates{sqlitePath, sqliteFile, sqliteTablesDefinitionPath})
		if initErr != nil {
			log.Fatal(initErr)
		}
		defer initDb.Close()
		log.Println(fmt.Sprintf("Client database '%s' created in '%s'", sqliteFile, sqlitePath))

	} else {
		// a regular scanner processing event

		// coordinates for connecting to the sqlite database (from the command line options)
		dbCoordinates := database.ConnCoordinates{DBPath: sqlitePath, DBFile: sqliteFile}

		// attempt to connect to the sqlite db
		db, dbErr := database.InitializeDB(dbCoordinates)
		if dbErr != nil {
			log.Fatal(dbErr)
		}
		defer db.Close()

		processScanFn := func(barcode string) {
			// Lookup the barcode in the API server
			apiResponse, apiErr := http.PostForm(fmt.Sprintf("%s:%d/lookup", apiServer, apiPort), url.Values{"barcode": {barcode}})
			if apiErr != nil {
				fmt.Println(fmt.Sprintf("API access error: %s", apiErr))
				return
			}
			rawJson, _ := ioutil.ReadAll(apiResponse.Body)
			apiResponse.Body.Close()

			var products []*commerce.API
			err := json.Unmarshal(rawJson, &products)
			if err != nil {
				fmt.Println(fmt.Sprintf("API barcode lookup error: %s", err))
				return
			}

			// get the Account for this request
			acc, accErr := database.GetDesignatedAccount(db)
			if accErr != nil {
				fmt.Println(fmt.Sprintf("Client db account access error: %s", accErr))
				return
			}

			// get the list of current Vendors according to the Pi client database
			// and map them according to their API vendor id string
			vendors := make(map[string]*database.Vendor)
			for _, v := range database.GetAllVendors(db) {
				vendors[v.VendorId] = v
			}

			productsFound := 0
			for i, product := range products {
				v, exists := vendors[product.Vendor]
				if !exists {
					if len(product.Vendor) > 0 {
						amazonId, amazonErr := database.AddVendor(db, product.Vendor, "Amazon")
						if amazonErr == nil {
							v = database.GetVendor(db, amazonId)
							vendors[product.Vendor] = v
							exists = true
						}
					}
				}

				if len(product.ProductName) > 0 {
					// convert the commerce.API struct into a database.Item
					// so that it can be logged into the Pi client sqlite db
					item := database.Item{
						Index:           int64(i),
						Barcode:         barcode,
						Desc:            product.ProductName,
						UserContributed: false}
					pk, insertErr := item.Add(db, acc)
					if insertErr == nil {
						// also log the vendor/product code combination
						if exists {
							database.AddVendorProduct(db, product.SKU, v.Id, pk)
						}
					}
					productsFound += 1
				}
			}

			if productsFound == 0 {
				// add it to the Pi client sqlite db as "unknown"
				// so that it can be manually edited/input
				unknownItem := database.Item{Index: 0, Barcode: barcode}
				unknownItem.Add(db, acc)
			}
		}

		errorFn := func(e error) {
			log.Fatal(e)
		}

		log.Println(fmt.Sprintf("Starting the scanner %s", device))
		scanner.ScanForever(device, processScanFn, errorFn)
	}
}
Beispiel #2
0
// getItems returns a list of scanned or favorited products, and the correct
// corresponding options for the HTML page template
func getItems(w http.ResponseWriter, r *http.Request, dbCoords database.ConnCoordinates, favorites bool) {
	// attempt to connect to the db
	db, err := database.InitializeDB(dbCoords)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer db.Close()

	// get the Account for this request
	acc, accErr := database.GetDesignatedAccount(db)
	if accErr != nil {
		http.Error(w, accErr.Error(), http.StatusInternalServerError)
		return
	}

	// define the appropriate fetch item function
	fetch := func(db *sqlite3.Conn, acc *database.Account) ([]*database.Item, error) {
		if favorites {
			return database.GetFavoriteItems(db, acc)
		} else {
			return database.GetItems(db, acc)
		}
	}

	// get all the desired items for this Account
	items := make([]*database.Item, 0)
	itemList, itemsErr := fetch(db, acc)
	if itemsErr != nil {
		http.Error(w, itemsErr.Error(), http.StatusInternalServerError)
		return
	}
	for _, item := range itemList {
		items = append(items, item)
	}

	// actions
	actions := make([]*Action, 0)
	// commerce options
	for _, vendor := range database.GetAllVendors(db) {
		actions = append(actions, &Action{Link: fmt.Sprintf("/buy%s/", vendor.VendorId), Icon: "fa fa-shopping-cart", Action: fmt.Sprintf("Buy from %s", vendor.DisplayName)})
	}
	if acc.Email != database.ANONYMOUS_EMAIL {
		actions = append(actions, &Action{Link: "/email/", Icon: "fa fa-envelope", Action: "Email to me"})
	}
	if favorites {
		actions = append(actions, &Action{Link: "/unfavorite/", Icon: "fa fa-star-o", Action: "Remove from favorites"})
	} else {
		actions = append(actions, &Action{Link: "/favorite/", Icon: "fa fa-star", Action: "Add to favorites"})
	}
	actions = append(actions, &Action{Link: "/delete/", Icon: "fa fa-trash", Action: "Delete"})

	// define the page title
	var titleBuffer bytes.Buffer
	if favorites {
		titleBuffer.WriteString("Favorite")
	} else {
		titleBuffer.WriteString("Scanned")
	}
	titleBuffer.WriteString(" Item")
	if len(itemList) != 1 {
		titleBuffer.WriteString("s")
	}

	p := &ItemsPage{Title: titleBuffer.String(),
		Scanned:   !favorites,
		ActiveTab: &ActiveTab{Scanned: !favorites, Favorites: favorites, Account: false, ShowTabs: true},
		Actions:   actions,
		Account:   acc,
		Items:     items}

	// check for any message to display on page load
	r.ParseForm()
	if msg, exists := r.Form["ack"]; exists {
		ackType := strings.Join(msg, "")
		if ackType == "email" {
			p.PageMessage = EMAIL_SENT
		}
	}

	renderItemListTemplate(w, p)
}