package main // import "blavote" import "fmt" import "github.com/mxk/go-sqlite/sqlite3" import "github.com/jessevdk/go-flags" import "os" import "io/ioutil" import "strings" import "strconv" import "errors" var version string func main() { version = "0.7" //Command line arguments var opts struct { Version bool `short:"v" long:"version" description:"Show program version"` Add string `short:"a" long:"add" description:"Title for a new poll"` New string `short:"n" long:"new" description:"Title for a new poll"` Username string `short:"u" long:"username" description:"Username of user adding poll"` Remove int `short:"r" long:"remove" description:"ID of a poll to delete"` Info int `short:"i" long:"info" description:"Get info and vote stats for a given poll ID"` List bool `short:"l" long:"list" description:"List recent polls"` Args struct { Rest []string } `positional-args:"yes"` } var args []string //If there are no command line arguments, read them from stdin if (len(os.Args) > 1) { flags.Parse(&opts) } else { bytes, err := ioutil.ReadAll(os.Stdin) if (err == nil) { args = strings.Split(strings.Split(string(bytes),"\n")[0], " ") flags.ParseArgs(&opts, args) } else { fmt.Println(err) //No args given, deal with it } } db, err := connectDb("blavote.db") if (err != nil) { fmt.Print("Could not connect to vote database: ") fmt.Println(err) return } if (opts.Version) { fmt.Println("v" + version) } else if (opts.Add != "") { fmt.Println(opts.Args.Rest) pollId, err := addPoll(db, opts.Add, opts.Args.Rest, opts.Username) if (err == nil) { fmt.Print("Poll added with ID ") fmt.Println(pollId) } else { fmt.Println(err) } } else if (opts.New != "") { pollId, err := addPoll(db, opts.New, opts.Args.Rest, opts.Username) if (err == nil) { fmt.Print("Poll added with ID ") fmt.Println(pollId) } else { fmt.Println(err) } } else if (opts.Remove > 0) { err = deletePoll(db, opts.Remove, opts.Username) if (err == nil) { fmt.Print("Poll removed with ID ") fmt.Println(opts.Remove) } else { fmt.Println(err) } } else if (opts.Info > 0) { err = pollInfo(db, opts.Info) } else if (opts.List) { err = listPolls(db) if (err != nil) { fmt.Println(err) } } else { if (len(opts.Args.Rest) > 1) { err = vote(db, opts.Username, opts.Args.Rest) if (err != nil) { fmt.Println(err) } } else { } } } func connectDb(name string) (*sqlite3.Conn, error) { db, err := sqlite3.Open(name) if (err != nil) { return nil, err } //Check the version in the DB, if it doesn't exist we'll create it //Can use this later to update the DB if needed sql := "select * from info where key = 'version'" _, err = db.Query(sql) if (err != nil) { fmt.Println("info table does not exist, creating database") initTables(db) return nil, err } return db, err } func initTables(db *sqlite3.Conn) { db.Exec("create table info(id int, key text, value text)") db.Exec("insert into info (key, value) values('version', '$a')", version) db.Exec("create table users(id integer primary key autoincrement, name text, admin boolean)") db.Exec("create table polls(id integer primary key autoincrement, title text, user_id int)") db.Exec("create table options(id integer primary key autoincrement, text text, poll_id int)") db.Exec("create table votes(id integer primary key autoincrement, user_id int, poll_id int, option_id int)") } func vote(db *sqlite3.Conn, nick string, options []string) error { pollId, err := strconv.Atoi(options[0]) if (err != nil) { return errors.New("Poll ID must be a number") } poll, err := getPollFromId(db, pollId) if (err != nil) { return err } option, err := getOptionFromText(db, options[1]) if (err != nil) { return err } user := getUserForName(db, nick) //Record the user in the DB if they aren't already if (user.id == 0) { user, err = createUser(db, nick, false) if (err != nil) { return err } } if (!hasUserVotedInPoll(db, poll, user)) { args := sqlite3.NamedArgs{"$a": user.id, "$b": poll.id, "$c": option.id} sql := "INSERT INTO votes (user_id, poll_id, option_id) VALUES ($a, $b, $c)" err = db.Exec(sql, args) if (err != nil ) { return err } else { fmt.Println("Vote added") return nil } } else { return errors.New("You have already voted in this poll") } } func pollInfo(db *sqlite3.Conn, id int) error { poll , err := getPollFromId(db, id) fmt.Print(poll.title + " - ") options, err := getOptionsForPoll(db, poll) for _, option := range options { option, err = getVotesForOption(db, option) fmt.Print(option.text + " (") fmt.Print(option.numVotes) fmt.Print(") ") } fmt.Println() return err } func listPolls(db *sqlite3.Conn) error { polls, err := getRecentPolls(db) for _, poll := range polls { if (poll.id != 0) { fmt.Print(poll.id) fmt.Print(": " + poll.title + " ") } else { fmt.Println() return nil } } return err }