Skip to content
Snippets Groups Projects
Select Git revision
  • a60342b7a4210e70782384b2d0b51bbe2afb3a63
  • master default protected
  • android-7.1.2_r28_klist
  • pie-cts-release
  • pie-vts-release
  • pie-cts-dev
  • oreo-mr1-iot-release
  • sdk-release
  • oreo-m6-s4-release
  • oreo-m4-s12-release
  • pie-release
  • pie-r2-release
  • pie-r2-s1-release
  • oreo-vts-release
  • oreo-cts-release
  • oreo-dev
  • oreo-mr1-dev
  • pie-gsi
  • pie-platform-release
  • pie-dev
  • oreo-cts-dev
  • android-o-mr1-iot-release-1.0.4
  • android-9.0.0_r8
  • android-9.0.0_r7
  • android-9.0.0_r6
  • android-9.0.0_r5
  • android-8.1.0_r46
  • android-8.1.0_r45
  • android-n-iot-release-smart-display-r2
  • android-vts-8.1_r5
  • android-cts-8.1_r8
  • android-cts-8.0_r12
  • android-cts-7.1_r20
  • android-cts-7.0_r24
  • android-o-mr1-iot-release-1.0.3
  • android-cts-9.0_r1
  • android-8.1.0_r43
  • android-8.1.0_r42
  • android-n-iot-release-smart-display
  • android-p-preview-5
  • android-9.0.0_r3
41 results

attributes

Blame
  • logic.go 10.11 KiB
    package main
    
    import (
    	"fmt"
    	"os"
    	"os/exec"
    	"path/filepath"
    	"regexp"
    	"sort"
    	"strconv"
    	"strings"
    )
    
    // maps user input to events
    type logicMatchEntry struct {
    	event func(string)
    	match *regexp.Regexp
    }
    
    // compile regex patterns and map to actions
    var (
    	logicMatchTable = map[string]*logicMatchEntry{
    		"logicSearch": &logicMatchEntry{logicSearch, regexp.MustCompile(`(?m)^[^\:]`)},
    		"logicNumber": &logicMatchEntry{logicNumber, regexp.MustCompile(`(?m)^\:[0-9]+(\ |$)`)},
    		"logicPage":   &logicMatchEntry{logicPage, regexp.MustCompile(`(?m)^\::[0-9]+$`)},
    		"logicSub":    &logicMatchEntry{logicSub, regexp.MustCompile(`(?m)^\:sub$`)}, // avoid matching conflict with subadd!
    		"logicSubAdd": &logicMatchEntry{logicSubAdd, regexp.MustCompile(`(?m)^\:subadd`)},
    		"logicSubDel": &logicMatchEntry{logicSubDel, regexp.MustCompile(`(?m)^\:subdel`)},
    		"logicUser":   &logicMatchEntry{logicUser, regexp.MustCompile(`(?m)^\:user`)},
    		"logicNew":    &logicMatchEntry{logicNew, regexp.MustCompile(`(?m)^\:new$`)},
    		"logicSet":    &logicMatchEntry{logicSet, regexp.MustCompile(`(?m)^\:set`)},
    		"logicHelp":   &logicMatchEntry{logicHelp, regexp.MustCompile(`(?m)^\:help`)},
    		"logicQuit":   &logicMatchEntry{logicQuit, regexp.MustCompile(`(?m)^\:q$`)},
    	}
    )
    
    type logicWindowState int
    
    // window states
    const (
    	logicWindowNone logicWindowState = iota
    	logicWindowSearch
    	logicWindowSub
    	logicWindowUser
    )
    
    var (
    	logicVarLineCount                   = 30
    	logicVarWindow                      = logicWindowNone
    	logicVarVideos    []*videoContainer = []*videoContainer{}
    	logicVarLazy                        = &listLazy{}
    	logicVarUsers                       = []string{}
    	logicVarUser                        = ""
    	logicVarSearch                      = ""
    )
    
    // logicAction parses the input string and performs the given action
    func logicAction(input string) {
    	// match pattern
    	logicMatch(input)(logicTrim(input))
    }
    
    // logicMatch returns the best fitting function for the given input
    func logicMatch(input string) func(string) {
    	for _, entry := range logicMatchTable {
    		if entry.match.MatchString(input) {
    			return entry.event
    		}
    	}
    	return logicUnknown
    }
    
    // logicTrim separates and returns the commands arguments
    func logicTrim(trim string) string {
    	if logicMatchTable["logicNumber"].match.MatchString(trim) {
    		return trim[1:]
    	}
    
    	if logicMatchTable["logicPage"].match.MatchString(trim) {
    		return trim[2:]
    	}
    
    	if strings.Index(trim, ":") == 0 {
    		out := strings.SplitN(trim, " ", 2)
    		if len(out) > 1 {
    			return out[1]
    		}
    		return ""
    	}
    
    	return trim
    }
    
    // logicSearch searches for the given video title
    func logicSearch(title string) {
    	upd := func(state int) []*videoContainer {
    		return videoListSearch(title, strconv.Itoa(state+1))
    	}
    
    	logicVarLazy = listNew(upd)
    	logicSearchPage("searching: "+title, 0)
    }
    
    //logicSearchPage searches the title in the given page
    func logicSearchPage(title string, page int) {
    	cliStatus("page " + strconv.Itoa(page) + " | " + title)
    	logicVarWindow = logicWindowSearch
    	logicVarSearch = title
    
    	list := logicVarLazy.listSlice(page*logicVarLineCount, (page+1)*logicVarLineCount)
    
    	if list == nil {
    		cliStatusError("network error: unable to load data")
    		return
    	}
    	if len(list) == 0 {
    		cliStatusError("no results for the given query")
    	}
    	logicList(-1, list)
    }
    
    // logicNumber selects the given list number
    func logicNumber(command string) {
    	splits := strings.SplitN(command, " ", 2)
    	player := logicGetPlayer()
    	if len(splits) > 1 {
    		player = splits[1]
    	}
    
    	sel, err := strconv.Atoi(splits[0])
    	errorCare(err)
    
    	switch logicVarWindow {
    	case logicWindowNone:
    		cliStatusError("error: video list is empty")
    	case logicWindowUser:
    		fallthrough
    	case logicWindowSearch:
    		if sel < len(logicVarVideos) {
    			logicPlay(player, sel) // non blocking
    		} else {
    			cliStatusError("error: video id not in list")
    		}
    	case logicWindowSub:
    		if sel < len(logicVarUsers) {
    			logicUser(logicVarUsers[sel])
    		} else {
    			cliStatusError("error: user id not in list")
    		}
    	}
    }
    
    // logicPage selects the given page
    func logicPage(page string) {
    	pnum, err := strconv.Atoi(page)
    	errorCare(err)
    
    	switch logicVarWindow {
    	case logicWindowSearch:
    		logicSearchPage(logicVarSearch, pnum)
    	case logicWindowUser:
    		logicUserPage(logicVarUser, pnum)
    	}
    }
    
    // logicGetUsers retieves a list of all subscripted users
    func logicGetUsers() []string {
    	subs, err := storeReadFile(storeDefaultSubscriptions)
    	errorCare(err)
    	users := []string{}
    
    	for _, user := range strings.Split(subs, "\n") {
    		if len(user) > 2 && user[0] == '"' && user[len(user)-1] == '"' {
    			users = append(users, user[1:len(user)-1])
    		}
    	}
    	return users
    }
    
    // logicSub lists the subscriptions
    func logicSub(none string) {
    	columns := 4
    
    	logicVarWindow = logicWindowSub
    	id := make([][]string, columns)
    	us := make([][]string, columns)
    
    	users := logicGetUsers()
    	sort.Strings(users)
    
    	newcol := len(users)/columns + 1
    	for i, u := range users {
    		id[i/newcol] = append(id[i/newcol], strconv.Itoa(i))
    		us[i/newcol] = append(us[i/newcol], u)
    	}
    
    	logicVarUsers = users
    	cliStatus("list of subscriptions")
    	cliTable(-1, id[0], us[0], id[1], us[1], id[2], us[2], id[3], us[3])
    }
    
    // logicSubAdd adds the given user to the subscription list
    func logicSubAdd(user string) {
    	if user == "" && logicVarWindow == logicWindowUser {
    		user = logicVarUser
    	}
    
    	if strings.Contains(user, "\"") {
    		cliStatusError("error: illicit username")
    		return
    	}
    
    	subs, err := storeReadFile(storeDefaultSubscriptions)
    	errorCare(err)
    
    	if strings.Contains(subs, "\""+user+"\"") {
    		cliStatusError("error: user '" + user + "' already in list")
    		return
    	}
    
    	errorCare(storeWriteFile(storeDefaultSubscriptions, subs+"\""+user+"\"\n"))
    	cliStatus("subscription '" + user + "' added")
    	cliClearDown()
    }
    
    // logicSubAdd adds the given user to the subscription list
    func logicSubDel(user string) {
    	if user == "" && logicVarWindow == logicWindowUser {
    		user = logicVarUser
    	}
    
    	if strings.Contains(user, "\"") {
    		cliStatusError("error: illicit username")
    		return
    	}
    
    	subs, err := storeReadFile(storeDefaultSubscriptions)
    	errorCare(err)
    
    	if !strings.Contains(subs, "\""+user+"\"") {
    		cliStatusError("error: user '" + user + "' not in list")
    		return
    	}
    
    	errorCare(storeWriteFile(storeDefaultSubscriptions, strings.Replace(subs, "\""+user+"\"\n", "", 1))) // meh
    	cliStatus("subscription '" + user + "' deleted")
    	cliClearDown()
    }
    
    // logicUser shows the videos of the given user
    func logicUser(user string) {
    	logicUserPage(user, 0)
    }
    
    // logicUserPage shows the page of the given user
    func logicUserPage(user string, page int) {
    	// TODO: support pages (priority: low)
    	cliStatus("page " + strconv.Itoa(page) + " | user: " + user)
    	logicVarWindow = logicWindowUser
    	logicVarUser = user
    	logicList(-1, videoListUser(user))
    }
    
    // logicNew shows a list of new videos
    func logicNew(none string) {
    	logicVarWindow = logicWindowSearch
    	logicVarSearch = ""
    	users := logicGetUsers()
    
    	upd := func(state int) []*videoContainer {
    		if state < len(users) {
    			return videoListUser(users[state])
    		}
    		return nil // all users updated (wont occur in reality)
    	}
    
    	logicVarLazy = listNew(upd)
    	cliStatus("updating users ...")
    	logicVarLazy.listPar(len(users))
    	logicVarLazy.listGet(0) // downloads all user pages as par = len(users)
    
    	cliHome()
    	fmt.Println()
    	cliStatus("sorting ...")
    	sort.Sort(&videoSort{logicVarLazy.listCached()})
    
    	logicSearchPage("new videos", 0)
    }
    
    // logicSet sets the key to the given value. Format: "key value"
    func logicSet(perform string) {
    	logicSetPlayer(perform)
    }
    
    // logicHelp shows the help
    func logicHelp(none string) {
    	cliStatus("available commands and usage")
    	cliClearDown()
    
    	help := `
    to search for a video simply input keywords
    
    commands:
    
    :[number] [player]   select list item (optional: video player)
    ::[number]           select list page
    :user [user]         show videos of user
    :sub                 show subscriptions
    :new                 show new subscribed videos
    :subadd [user]       add given or current user
    :subdel [user]       delete given or current user
    :set [player]        set default video player
    :help                show this help
    :q                   quit the program
    `
    
    	fmt.Println(help)
    }
    
    // logicUnknown shows a message if the command could not be parsed
    func logicUnknown(command string) {
    	cliStatusError("error: unknown command")
    }
    
    // logicQuit exits the program
    func logicQuit(none string) {
    	cliReset()
    	os.Exit(0)
    }
    
    // logicList shows a video list and highlights the line with the given
    // line number. If hightlight < 0 no line will be highlighted.
    // The global video list logicVarVideos will be set by this function.
    func logicList(highlight int, videos []*videoContainer) {
    	logicVarVideos = videos
    
    	cliClearDown()
    	id, titles, urls, durations, users, dates, views := []string{}, []string{}, []string{}, []string{}, []string{}, []string{}, []string{}
    	for i, v := range videos {
    		id = append(id, strconv.Itoa(i))
    		titles = append(titles, cliTrimLength(v.title, " >>", 55))
    		urls = append(urls, v.url)
    		durations = append(durations, v.duration)
    		users = append(users, v.user)
    		dates = append(dates, v.date)
    		views = append(views, v.views)
    	}
    	cliTable(highlight, id, titles, durations, users, views, dates)
    }
    
    // logicGetPlayer gets the default video player
    func logicGetPlayer() string {
    	player, err := storeReadFile(storeDefaultPlayer)
    	errorCare(err)
    
    	return strings.Replace(player, "\n", "", -1)
    }
    
    // logicSetPlayer sets the default video player
    func logicSetPlayer(player string) {
    	errorCare(storeWriteFile(storeDefaultPlayer, player))
    	cliStatus("default player set to '" + player + "'")
    	cliClearDown()
    }
    
    // logicPlay plays the video with the given video id in the player
    func logicPlay(player string, id int) {
    	video := logicVarVideos[id]
    	cmd := append(strings.Split(player, " "), "https://www.youtube.com/watch?v="+video.url)
    
    	script := filepath.Join(storeDefaultScripts, cmd[0])
    	exists, err := storeFileExists(script)
    	errorCare(err)
    	if exists {
    		cmd[0] = script
    		player = "$" + player // visual indicator for user script
    	}
    
    	exe := exec.Command(cmd[0], cmd[1:]...)
    	if err := exe.Start(); err != nil {
    		cliStatusError(fmt.Sprint("playback error: ", err))
    	} else {
    		cliStatus("[" + player + "] " + video.title)
    		logicList(id, logicVarVideos)
    	}
    	go exe.Wait()
    }