Пример #1
0
func (d *Dal) Start() {
	mlog.Info("Starting service Dal ...")

	dbPath := filepath.Join(d.settings.DataDir, "mediagui.db")

	var err error
	d.db, err = sql.Open("sqlite3", dbPath)
	if err != nil {
		mlog.Fatalf("Unable to open database (%s): %s", dbPath, err)
	}

	d.mailbox = d.register(d.bus, "/get/movies/cover", d.getCover)
	d.registerAdditional(d.bus, "/get/movies", d.getMovies, d.mailbox)
	d.registerAdditional(d.bus, "/get/movies/duplicates", d.getDuplicates, d.mailbox)
	d.registerAdditional(d.bus, "/command/movie/exists", d.checkExists, d.mailbox)
	d.registerAdditional(d.bus, "/command/movie/store", d.storeMovie, d.mailbox)
	d.registerAdditional(d.bus, "/command/movie/partialstore", d.partialStoreMovie, d.mailbox)
	d.registerAdditional(d.bus, "/command/movie/update", d.updateMovie, d.mailbox)
	d.registerAdditional(d.bus, "/command/movie/delete", d.deleteMovie, d.mailbox)
	d.registerAdditional(d.bus, "/put/movies/score", d.setScore, d.mailbox)
	d.registerAdditional(d.bus, "/put/movies/watched", d.setWatched, d.mailbox)

	d.countRows = d.prepare("select count(*) from movie;")

	mlog.Info("Connected to database %s", dbPath)

	go d.react()
}
Пример #2
0
func (s *ReScrape) Execute(wid int) {
	movie := s.dto.Movie.(*model.Movie)

	// lib.Notify(s.bus, "import:progress", fmt.Sprintf("RESCRAPE REQUESTED (%d) [%d] %s", wid, movie.Id, movie.Title))
	mlog.Info("RESCRAPE REQUESTED (%d) [%d] %s", wid, movie.Id, movie.Title)

	now := time.Now().UTC().Format(time.RFC3339)
	movie.Modified = now

	id := movie.Tmdb_Id

	err := _scrape(wid, s.tmdb, id, movie)
	if err != nil {
		// lib.Notify(s.bus, "import:progress", fmt.Sprintf("RESCRAPE FAILED (%d) [%d] %s: %s", wid, movie.Id, movie.Title, err))
		mlog.Warning("RESCRAPE FAILED (%d) [%d] %s: %s", wid, movie.Id, movie.Title, err)
		s.bus.Pub(nil, "/event/workunit/done")

		return
	}

	s.dto.BaseUrl = s.tmdb.BaseUrl
	s.dto.SecureBaseUrl = s.tmdb.SecureBaseUrl

	// lib.Notify(s.bus, "import:progress", fmt.Sprintf("RESCRAPE COMPLETED (%d) [%d] %s", wid, movie.Id, movie.Title))
	mlog.Info("RESCRAPE COMPLETED (%d) [%d] %s", wid, movie.Id, movie.Title)

	msg := &pubsub.Message{Payload: s.dto}
	s.bus.Pub(msg, "/event/movie/rescraped")
}
Пример #3
0
func (d *Dal) setScore(msg *pubsub.Message) {
	movie := msg.Payload.(*model.Movie)

	mlog.Info("STARTED UPDATING MOVIE SCORE [%d] %s (%d)", movie.Id, movie.Title, movie.Score)

	tx, err := d.db.Begin()
	if err != nil {
		mlog.Fatalf("at begin: %s", err)
	}

	stmt, err := tx.Prepare(`update movie set 
								score = ?,
								modified = ? 
								where rowid = ?`)
	if err != nil {
		tx.Rollback()
		mlog.Fatalf("at prepare: %s", err)
	}
	defer stmt.Close()

	now := time.Now().UTC().Format(time.RFC3339)

	_, err = stmt.Exec(movie.Score, now, movie.Id)
	if err != nil {
		tx.Rollback()
		mlog.Fatalf("at exec: %s", err)
	}

	tx.Commit()
	mlog.Info("FINISHED UPDATING MOVIE SCORE [%d] %s", movie.Id, movie.Title)

	msg.Reply <- movie
}
Пример #4
0
func (d *Dal) updateMovie(msg *pubsub.Message) {
	defer d.bus.Pub(nil, "/event/workunit/done")

	movie := msg.Payload.(*model.Movie)

	mlog.Info("STARTED UPDATING [%d] %s", movie.Id, movie.Title)

	tx, err := d.db.Begin()
	if err != nil {
		mlog.Fatalf("at begin: %s", err)
	}

	stmt, err := tx.Prepare(`update movie set title = ?, 
								original_title = ?, 
								year = ?, 
								runtime = ?, 
								tmdb_id = ?, 
								imdb_id = ?, 
								overview = ?, 
								tagline = ?, 
								cover = ?, 
								backdrop = ?, 
								genres = ?, 
								vote_average = ?, 
								vote_count = ?, 
								countries = ?, 
								modified = ?, 
								director = ?, 
								writer = ?, 
								actors = ?, 
								awards = ?, 
								imdb_rating = ?, 
								imdb_votes = ? 
								where rowid = ?`)
	if err != nil {
		tx.Rollback()
		mlog.Fatalf("at prepare: %s", err)
	}
	defer stmt.Close()

	_, err = stmt.Exec(movie.Title, movie.Original_Title, movie.Year, movie.Runtime, movie.Tmdb_Id, movie.Imdb_Id, movie.Overview, movie.Tagline, movie.Cover, movie.Backdrop, movie.Genres, movie.Vote_Average, movie.Vote_Count, movie.Production_Countries, movie.Modified, movie.Director, movie.Writer, movie.Actors, movie.Awards, movie.Imdb_Rating, movie.Imdb_Votes, movie.Id)
	if err != nil {
		tx.Rollback()
		mlog.Fatalf("at exec: %s", err)
	}

	tx.Commit()
	mlog.Info("FINISHED UPDATING [%d] %s", movie.Id, movie.Title)

	// updated := &pubsub.Message{}
	// d.bus.Pub(updated, "/event/movie/updated")
}
Пример #5
0
func (s *Scanner) Start() {
	mlog.Info("Starting service Scanner ...")

	s.mailbox = s.register(s.bus, "/command/movie/scan", s.scanMovies)
	s.registerAdditional(s.bus, "/event/config/changed", s.configChanged, s.mailbox)

	re := []string{
		`(?i)(.*)/(?P<Resolution>.*?)/(?P<Name>.*?)\s\((?P<Year>\d\d\d\d)\)/(?:.*/)*bdmv/index.(?P<FileType>bdmv)$`,
		`(?i)(.*)/(?P<Resolution>.*?)/(?P<Name>.*?)\s\((?P<Year>\d\d\d\d)\)/(?:.*/)*.*\.(?P<FileType>iso|img|nrg|mkv|avi|xvid|ts|mpg|dvr-ms|mdf|wmv|mp4)$`,
		`(?i)(.*)/(?P<Resolution>.*?)/(?P<Name>.*?)\s\((?P<Year>\d\d\d\d)\)/(?:.*/)*(?:video_ts|hv000i01)\.(?P<FileType>ifo)$`,
		// `(?i)(?P<Name>.*?)\s\((?P<Year>\d\d\d\d)\)/(?:.*/)*bdmv/index.(?P<FileType>bdmv)$`,
		// `(?i)(?P<Name>.*?)\s\((?P<Year>\d\d\d\d)\)/(?:.*/)*.*\.(?P<FileType>iso|img|nrg|mkv|avi|xvid|ts|mpg|dvr-ms|mdf|wmv)$`,
		// `(?i)(?P<Name>.*?)\s\((?P<Year>\d\d\d\d)\)/(?:.*/)*(?:video_ts|hv000i01)\.(?P<FileType>ifo)$`,
		// `(?i)(?P<Name>.*?)\s\((?P<Year>\d\d\d\d)\)\.(?P<FileType>iso|img|nrg|mkv|avi|xvid|ts|mpg|dvr-ms|mdf|wmv)$`,
	}

	s.re = make([]*lib.Rexp, 0)
	for _, regex := range re {
		s.re = append(s.re, &lib.Rexp{Exp: regexp.MustCompile(regex)})
	}

	s.includedMask = ".bdmv|.iso|.img|.nrg|.mkv|.avi|.xvid|.ts|.mpg|.dvr-ms|.mdf|.wmv|.ifo|.mp4"

	// cmd.Init()

	go s.react()
}
Пример #6
0
func (s *Scanner) analyze(files []string) {
	mlog.Info("Found %d files", len(files))

	for _, file := range files {
		// comparePath := strings.TrimPrefix(path, file)
		// mlog.Info("folder: %s, comparePath: %s", folder, comparePath)
		// TODO: remove folder from path to match against rexp

		for i := 0; i < 3; i++ {
			rmap := s.re[i].Match(file)
			if rmap == nil {
				continue
			}

			resolution, ok := rmap["Resolution"]
			if !ok {
				resolution = ""
			}

			movie := &model.Movie{Title: rmap["Name"], File_Title: rmap["Name"], Year: rmap["Year"], Resolution: resolution, FileType: rmap["FileType"], Location: file}
			// mlog.Info("FOUND [%s] (%s)", movie.Title, movie.Location)

			// mlog.Info("found %s", movie.Location)
			msg := &pubsub.Message{Payload: movie}
			s.bus.Pub(msg, "/event/movie/found")
			// self.Bus.MovieFound <- movie
		}
	}
}
Пример #7
0
func (c *Core) Start() {
	mlog.Info("Starting service Core ...")

	c.mailbox = c.register(c.bus, "/get/config", c.getConfig)
	c.registerAdditional(c.bus, "/post/import", c.importMovies, c.mailbox)
	c.registerAdditional(c.bus, "/post/prune", c.pruneMovies, c.mailbox)
	c.registerAdditional(c.bus, "/put/config/folder", c.addMediaFolder, c.mailbox)
	c.registerAdditional(c.bus, "/put/movies/fix", c.fixMovie, c.mailbox)

	c.registerAdditional(c.bus, "/event/movie/found", c.doMovieFound, c.mailbox)
	c.registerAdditional(c.bus, "/event/movie/tmdbnotfound", c.doMovieTmdbNotFound, c.mailbox)
	c.registerAdditional(c.bus, "/event/movie/scraped", c.doMovieScraped, c.mailbox)
	c.registerAdditional(c.bus, "/event/movie/rescraped", c.doMovieReScraped, c.mailbox)
	// c.registerAdditional(c.bus, "/event/movie/updated", c.doMovieUpdated, c.mailbox)
	// c.registerAdditional(c.bus, "/event/movie/cached/forced", c.doMovieCachedForced, c.mailbox)

	c.registerAdditional(c.bus, "/event/workunit/done", c.doWorkUnitDone, c.mailbox)

	c.re = regexp.MustCompile(`(?i)/Volumes/(.*?)/.*`)
	c.maps = make(map[string]bool)

	// maps["/Volumes/wopr-films"] = true // for example
	for _, folder := range c.settings.MediaFolders {
		c.maps[folder] = false
		if _, err := os.Stat(folder); err == nil {
			c.maps[folder] = true
		}
	}

	go c.react()
}
Пример #8
0
func (d *Dal) partialStoreMovie(msg *pubsub.Message) {
	defer d.bus.Pub(nil, "/event/workunit/done")

	movie := msg.Payload.(*model.Movie)

	// d.count = 0
	now := time.Now().UTC().Format(time.RFC3339)
	movie.Added = now
	movie.Modified = now

	mlog.Info("STARTED PARTIAL SAVING %s", movie.Title)

	tx, err := d.db.Begin()
	if err != nil {
		mlog.Fatalf("at begin: %s", err)
	}

	stmt, err := tx.Prepare(`insert into movie(title, original_title, file_title, 
								year, runtime, tmdb_id, imdb_id, overview, tagline, 
								resolution, filetype, location, cover, backdrop, genres, 
								vote_average, vote_count, countries, added, modified, 
								last_watched, all_watched, count_watched, score, director, 
								writer, actors, awards, imdb_rating, imdb_votes) 
								values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
									?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
	if err != nil {
		tx.Rollback()
		mlog.Fatalf("at prepare: %s", err)
	}
	defer stmt.Close()

	_, err = stmt.Exec(movie.Title, movie.Original_Title, movie.File_Title, movie.Year,
		movie.Runtime, movie.Tmdb_Id, movie.Imdb_Id, movie.Overview, movie.Tagline,
		movie.Resolution, movie.FileType, movie.Location, movie.Cover, movie.Backdrop,
		movie.Genres, movie.Vote_Average, movie.Vote_Count, movie.Production_Countries,
		movie.Added, movie.Modified, movie.Last_Watched, movie.All_Watched, movie.Count_Watched,
		movie.Score, movie.Director, movie.Writer, movie.Actors, movie.Awards, movie.Imdb_Rating,
		movie.Imdb_Votes)
	if err != nil {
		tx.Rollback()
		mlog.Fatalf("at exec: %s", err)
	}

	tx.Commit()
	mlog.Info("FINISHED PARTIAL SAVING %s [%d]", movie.Title, movie.Id)
}
Пример #9
0
func (d *Dal) listMovies(options *lib.Options) (total uint64, movies []*model.Movie) {
	// mlog.Info("listMovies.options: %+v", options)

	tx, err := d.db.Begin()
	if err != nil {
		mlog.Fatalf("listMovies:Unable to begin transaction: %s", err)
	}

	sql := fmt.Sprintf(`select rowid, title, original_title, file_title, year, runtime, tmdb_id, imdb_id, 
				overview, tagline, resolution, filetype, location, cover, backdrop, genres, vote_average, 
				vote_count, countries, added, modified, last_watched, all_watched, count_watched, score, 
				director, writer, actors, awards, imdb_rating, imdb_votes 
				from movie order by %s %s, rowid desc limit ? offset ?`, options.SortBy, options.SortOrder)

	stmt, err := tx.Prepare(sql)
	if err != nil {
		mlog.Fatalf("Unable to prepare transaction: %s", err)
	}
	defer stmt.Close()

	rows, err := stmt.Query(options.Limit, options.Offset)
	if err != nil {
		mlog.Fatalf("Unable to prepare transaction: %s", err)
	}

	items := make([]*model.Movie, 0)

	// if options.Offset == 0 {
	// if d.count == 0 {
	var count uint64

	err = d.countRows.QueryRow().Scan(&count)
	if err != nil {
		mlog.Fatalf("Unable to count rows: %s", err)
	}
	// }

	for rows.Next() {
		movie := model.Movie{}
		rows.Scan(
			&movie.Id, &movie.Title, &movie.Original_Title, &movie.File_Title, &movie.Year,
			&movie.Runtime, &movie.Tmdb_Id, &movie.Imdb_Id, &movie.Overview, &movie.Tagline,
			&movie.Resolution, &movie.FileType, &movie.Location, &movie.Cover, &movie.Backdrop,
			&movie.Genres, &movie.Vote_Average, &movie.Vote_Count, &movie.Production_Countries,
			&movie.Added, &movie.Modified, &movie.Last_Watched, &movie.All_Watched,
			&movie.Count_Watched, &movie.Score, &movie.Director, &movie.Writer, &movie.Actors,
			&movie.Awards, &movie.Imdb_Rating, &movie.Imdb_Votes,
		)
		items = append(items, &movie)
	}
	rows.Close()

	tx.Commit()

	mlog.Info("Listed %d movies (total %d)", len(items), count)

	return count, items
}
Пример #10
0
func (c *Cache) Start() {
	mlog.Info("Starting service Cache ...")

	c.mailbox = c.register(c.bus, "/command/movie/cache", c.cacheMovie)

	c.pool = lib.NewPool(4, 2000)

	go c.react()
}
Пример #11
0
func (d *Dal) getDuplicates(msg *pubsub.Message) {
	mlog.Info("getDuplicates.starting")

	tx, err := d.db.Begin()
	if err != nil {
		mlog.Fatalf("Unable to begin transaction: %s", err)
	}

	// rows, err := self.listMovies.Query()
	// if err != nil {
	// 	mlog.Fatalf("unable to prepare transaction: %s", err)
	// }

	// rows, err := self.db.Query("select rowid, title, original_title, file_title, year, runtime, tmdb_id, imdb_id, overview, tagline, resolution, filetype, location, cover, backdrop, genres, vote_average, vote_count, countries, added, modified, last_watched, all_watched, count_watched from movie where title in (select title from movie group by title having count(*) > 1);")
	rows, err := d.db.Query(`select a.rowid, a.title, a.original_title, a.file_title, 
				a.year, a.runtime, a.tmdb_id, a.imdb_id, a.overview, a.tagline, a.resolution, 
				a.filetype, a.location, a.cover, a.backdrop, a.genres, a.vote_average, 
				a.vote_count, a.countries, a.added, a.modified, a.last_watched, a.all_watched, 
				a.count_watched, a.score, a.director, a.writer, a.actors, a.awards, a.imdb_rating, 
				a.imdb_votes 
				from 
				movie a 
				join 
				(select title, year from movie group by title, year having count(*) > 1) b 
				on a.title = b.title and a.year = b.year;`)
	if err != nil {
		mlog.Fatalf("Unable to prepare transaction: %s", err)
	}

	items := make([]*model.Movie, 0)

	for rows.Next() {
		movie := model.Movie{}
		rows.Scan(&movie.Id, &movie.Title, &movie.Original_Title, &movie.File_Title, &movie.Year, &movie.Runtime, &movie.Tmdb_Id, &movie.Imdb_Id, &movie.Overview, &movie.Tagline, &movie.Resolution, &movie.FileType, &movie.Location, &movie.Cover, &movie.Backdrop, &movie.Genres, &movie.Vote_Average, &movie.Vote_Count, &movie.Production_Countries, &movie.Added, &movie.Modified, &movie.Last_Watched, &movie.All_Watched, &movie.Count_Watched, &movie.Score, &movie.Director, &movie.Writer, &movie.Actors, &movie.Awards, &movie.Imdb_Rating, &movie.Imdb_Votes)
		items = append(items, &movie)
	}
	rows.Close()

	tx.Commit()

	mlog.Info("Found %d duplicate movies", len(items))

	msg.Reply <- &model.MoviesDTO{Total: uint64(len(items)), Items: items}
}
Пример #12
0
func (c *Core) addMediaFolder(msg *pubsub.Message) {
	folder := msg.Payload.(string)
	mlog.Info("addMediaFolder: %s", folder)

	c.settings.MediaFolders = append(c.settings.MediaFolders, folder)
	c.settings.Save()

	cfg := &pubsub.Message{Payload: c.settings}
	c.bus.Pub(cfg, "/event/config/changed")

	msg.Reply <- &c.settings.Config
	// mlog.Info("Sent config")
}
Пример #13
0
func (d *Dal) getMovies(msg *pubsub.Message) {
	options := msg.Payload.(*lib.Options)

	mlog.Info("options: %+v", options)

	var total uint64
	var items []*model.Movie

	if options.Query == "" {
		total, items = d.listMovies(options)
	} else {
		total, items = d.searchMovies(options)
	}

	msg.Reply <- &model.MoviesDTO{Total: total, Items: items}
}
Пример #14
0
func (s *Scraper) Start() {
	mlog.Info("Starting service Scraper ...")

	var err error
	s.tmdb, err = tmdb.NewClient("e610ded10c3f47d05fe797961d90fea6", false)
	if err != nil {
		mlog.Fatalf("Unable to create tmdb client: %s", err)
	}

	s.mailbox = s.register(s.bus, "/command/movie/scrape", s.scrapeMovie)
	s.registerAdditional(s.bus, "/command/movie/rescrape", s.reScrapeMovie, s.mailbox)
	s.registerAdditional(s.bus, "/event/config/changed", s.configChanged, s.mailbox)

	s.pool = lib.NewPool(12, 4000)

	go s.react()
}
Пример #15
0
func (s *Scanner) walk(folder string) error {
	if folder[len(folder)-1] != '/' {
		folder = folder + "/"
	}

	err := filepath.Walk(folder, func(path string, f os.FileInfo, err error) error {
		if err != nil {
			mlog.Info("scanner.walk: %s (%s) - [%+v]", err, path, f)
		}

		if !strings.Contains(s.includedMask, strings.ToLower(filepath.Ext(path))) {
			// mlog.Info("[%s] excluding %s", filepath.Ext(path), path)
			return nil
		}

		// comparePath := strings.TrimPrefix(path, folder)
		// mlog.Info("folder: %s, comparePath: %s", folder, comparePath)
		// TODO: remove folder from path to match against rexp

		for i := 0; i < 3; i++ {
			var rmap = s.re[i].Match(path)
			if rmap == nil {
				continue
			}

			var resolution string
			var ok bool
			if resolution, ok = rmap["Resolution"]; !ok {
				resolution = ""
			}

			movie := &model.Movie{Title: rmap["Name"], File_Title: rmap["Name"], Year: rmap["Year"], Resolution: resolution, FileType: rmap["FileType"], Location: path}
			// mlog.Info("FOUND [%s] (%s)", movie.Title, movie.Location)

			msg := &pubsub.Message{Payload: movie}
			s.bus.Pub(msg, "/event/movie/found")
			// self.Bus.MovieFound <- movie

			return nil
		}

		return nil
	})

	return err
}
Пример #16
0
func (c *Core) doMovieFound(msg *pubsub.Message) {
	movie := msg.Payload.(*model.Movie)

	check := &pubsub.Message{Payload: movie, Reply: make(chan interface{}, 3)}
	c.bus.Pub(check, "/command/movie/exists")

	reply := <-check.Reply
	exists := reply.(bool)

	if exists {
		mlog.Info("SKIPPED: exists [%s] (%s)", movie.Title, movie.Location)
	} else {
		lib.Notify(c.bus, "import:progress", fmt.Sprintf("NEW: [%s] (%s)", movie.Title, movie.Location))

		c.wg.Add(1)
		c.bus.Pub(msg, "/command/movie/scrape")
	}
}
Пример #17
0
func (c *Core) doMovieReScraped(msg *pubsub.Message) {
	dto := msg.Payload.(*dto.Scrape)

	mlog.Info("ScrapeDTO: %+v", dto)

	// I treat the following two commands as one, for the sake of the wg
	// now there are two oustanding locks, which will be decreased by each
	// responding service
	c.wg.Add(1)

	store := &pubsub.Message{Payload: dto.Movie, Reply: make(chan interface{}, 3)}
	c.bus.Pub(store, "/command/movie/update")

	cache := &pubsub.Message{Payload: dto, Reply: make(chan interface{}, 3)}
	c.bus.Pub(cache, "/command/movie/cache")

	// mlog.Info("ScrapeDTO: %+v", dto)
}
Пример #18
0
func (c *Connection) Writer() {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
		c.Ws.Close()
	}()

	// mlog.Info("before write loop")

	for {
		select {
		case message, ok := <-c.Send:
			if !ok {
				c.write(websocket.CloseMessage, []byte{})
				mlog.Warning("Closing socket ...")
				return
			}

			if err := c.write(websocket.TextMessage, message); err != nil {
				mlog.Warning("Unable to write to websocket: %s", err.Error())
				return
			}

			// c.Ws.SetWriteDeadline(time.Now().Add(writeWait))
			// if err := c.Ws.WriteJSON(message); err != nil {
			// 	mlog.Error(err)
			// 	return
			// }
		case <-ticker.C:
			if err := c.write(websocket.PingMessage, []byte{}); err != nil {
				mlog.Info("error with ping: %s", err.Error())
				return
			}
		}
	}

}
Пример #19
0
func (c *Core) Stop() {
	mlog.Info("Stopped service Core ...")
}
Пример #20
0
func main() {
	// look for mediagui.conf at the following places
	// $HOME/.mediagui/mediagui.conf
	// /usr/local/etc/mediagui.conf
	// <current dir>/mediagui.conf
	home := os.Getenv("HOME")

	cwd, err := os.Getwd()
	if err != nil {
		log.Printf("Unable to get current directory: %s", err.Error())
		os.Exit(1)
	}

	locations := []string{
		filepath.Join(home, ".mediagui/mediagui.conf"),
		"/usr/local/etc/mediagui.conf",
		filepath.Join(cwd, "mediagui.conf"),
	}

	settings, err := lib.NewSettings(Version, home, locations)
	if err != nil {
		log.Printf("Unable to start the app: %s", err.Error())
		os.Exit(2)
	}

	if settings.CpuProfile != "" {
		f, err := os.Create(settings.CpuProfile)
		if err != nil {
			log.Printf("Unable to set up profiling: %s", err)
			os.Exit(3)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if settings.LogDir != "" {
		mlog.Start(mlog.LevelInfo, filepath.Join(settings.LogDir, "mediagui.log"))
	} else {
		mlog.Start(mlog.LevelInfo, "")
	}

	mlog.Info("mediagui v%s starting ...", Version)
	mlog.Info("using config file located at %s", settings.Location)

	bus := pubsub.New(8623)

	dal := services.NewDal(bus, settings)
	socket := services.NewSocket(bus, settings)
	server := services.NewServer(bus, settings)
	scanner := services.NewScanner(bus, settings)
	scraper := services.NewScraper(bus, settings)
	cache := services.NewCache(bus, settings)
	core := services.NewCore(bus, settings)

	dal.Start()
	socket.Start()
	server.Start()
	scanner.Start()
	scraper.Start()
	cache.Start()
	core.Start()

	mlog.Info("Press Ctrl+C to stop ...")

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
	mlog.Info("Received signal: (%s) ... shutting down the app now ...", <-c)

	core.Stop()
	cache.Stop()
	scraper.Stop()
	scanner.Stop()
	server.Stop()
	socket.Stop()
	dal.Stop()

	mlog.Stop()
}
Пример #21
0
func (d *Dal) Stop() {
	mlog.Info("Stopped service Dal ...")
}
Пример #22
0
func (d *Dal) setWatched(msg *pubsub.Message) {
	dto := msg.Payload.(*model.Movie)

	mlog.Info("STARTED UPDATING MOVIE WATCHED DATE [%d] %s (%s)", dto.Id, dto.Title, dto.Last_Watched)

	now := time.Now().UTC().Format(time.RFC3339)

	stmt, err := d.db.Prepare("select all_watched from movie where rowid = ?")
	if err != nil {
		mlog.Fatalf("at prepare: %s", err)
	}

	// get all watched times from the db
	var when string
	err = stmt.QueryRow(dto.Id).Scan(&when)
	if err != nil {
		mlog.Fatalf("at queryrow: %s", err)
	}

	// create an array with all watched times
	var watched_times []string
	if when != "" {
		watched_times = strings.Split(when, "|")
	}

	// convert incoming watched time to sane format
	watched, err := parseToday(dto.Last_Watched)
	if err != nil {
		mlog.Fatalf("at parseToday: %s", err)
	}
	last_watched := watched.UTC().Format(time.RFC3339)

	// add last watched to array, only if it doesn't already exist
	if !strings.Contains(when, last_watched) {
		watched_times = append(watched_times, last_watched)
	}

	// this sorts the dates in ascending order by default
	sort.Strings(watched_times)

	// set final variables
	last_watched = watched_times[len(watched_times)-1]
	count_watched := uint64(len(watched_times))
	all_watched := strings.Join(watched_times, "|")

	// var all_watched string
	// count_watched := dto.Count_Watched
	// if !strings.Contains(dto.All_Watched, dto.Last_Watched) {
	// 	count_watched++
	// 	if dto.All_Watched == "" {
	// 		all_watched = dto.Last_Watched
	// 	} else {
	// 		all_watched += "|" + dto.Last_Watched
	// 	}
	// }

	tx, err := d.db.Begin()
	if err != nil {
		mlog.Fatalf("at begin: %s", err)
	}

	stmt, err = tx.Prepare(`update movie set 
								last_watched = ?, 
								all_watched = ?, 
								count_watched = ?, 
								modified = ? 
								where rowid = ?`)
	if err != nil {
		tx.Rollback()
		mlog.Fatalf("at prepare: %s", err)
	}
	defer stmt.Close()

	_, err = stmt.Exec(last_watched, all_watched, count_watched, now, dto.Id)
	if err != nil {
		tx.Rollback()
		mlog.Fatalf("at exec: %s", err)
	}

	tx.Commit()
	mlog.Info("FINISHED UPDATING MOVIE WATCHED DATE [%d] %s", dto.Id, dto.Title)

	dto.All_Watched = all_watched
	dto.Count_Watched = count_watched
	dto.Modified = now

	msg.Reply <- dto
}
Пример #23
0
func (c *Core) getConfig(msg *pubsub.Message) {
	msg.Reply <- &c.settings.Config
	mlog.Info("Sent config")
}
Пример #24
0
func (c *Cache) Stop() {
	mlog.Info("Stopped service Cache")
}
Пример #25
0
func TestScraper(t *testing.T) {
	// look for mediagui.conf at the following places
	// $HOME/.mediagui/mediagui.conf
	// /usr/local/etc/mediagui.conf
	// <current dir>/mediagui.conf
	home := os.Getenv("HOME")

	cwd, err := os.Getwd()
	if err != nil {
		log.Printf("Unable to get current directory: %s", err.Error())
		os.Exit(1)
	}

	locations := []string{
		filepath.Join(home, ".mediagui/mediagui.conf"),
		"/usr/local/etc/mediagui.conf",
		filepath.Join(cwd, "mediagui.conf"),
	}

	settings, err := lib.NewSettings(Version, home, locations)
	if err != nil {
		log.Printf("Unable to start the app: %s", err.Error())
		os.Exit(2)
	}

	mlog.Start(mlog.LevelInfo, "")

	mlog.Info("mediagui v%s starting ...", Version)

	bus := pubsub.New(623)

	dal := services.NewDal(bus, settings)

	// socket.Start()
	dal.Start()

	movie := &model.Movie{
		Location: "wopr:/mnt/user/films/xvid/Visitor Q (2001)/ils-visitorq.avi",
	}

	check := &pubsub.Message{Payload: movie, Reply: make(chan interface{}, 3)}
	bus.Pub(check, "/command/movie/exists")

	reply := <-check.Reply
	exists := reply.(bool)

	if exists {
		mlog.Info("SKIPPED: exists [%s] (%s)", movie.Title, movie.Location)
	} else {
		mlog.Info("NEW: [%s] (%s)", movie.Title, movie.Location)
		// c.bus.Pub(msg, "/command/movie/scrape")
	}

	// mlog.Info("Press Ctrl+C to stop ...")

	// c := make(chan os.Signal, 1)
	// signal.Notify(c, os.Interrupt)
	// for _ = range c {
	// 	mlog.Info("Received an interrupt, shutting the app down ...")

	dal.Stop()

	// 	break
	// }
}
Пример #26
0
func (s *Scanner) Stop() {
	mlog.Info("Stopped service Scanner ...")
}
Пример #27
0
func (d *Dal) searchByYear(options *lib.Options) (total uint64, movies []*model.Movie) {
	var start, end, year uint64
	var decade bool = false

	if strings.Contains(options.Query, "-") {
		decade = true
		parts := strings.Split(options.Query, "-")

		start, _ = strconv.ParseUint(parts[0], 0, 64)
		end, _ = strconv.ParseUint(parts[1], 0, 64)
	} else {
		year, _ = strconv.ParseUint(options.Query, 0, 64)
	}

	var countQuery string
	if decade {
		countQuery = `select count(*) from movie where year between ? and ?;`
	} else {
		countQuery = `select count(*) from movie where year = ?;`
	}

	// mlog.Info("this is: %s %s", term, args)

	tx, err := d.db.Begin()
	if err != nil {
		mlog.Fatalf("searchByYear:Unable to begin transaction: %s", err)
	}

	stmt, err := tx.Prepare(countQuery)
	if err != nil {
		mlog.Fatalf("searchByYear:Unable to prepare transaction: %s", err)
	}
	defer stmt.Close()

	var count uint64

	var rows *sql.Rows
	if decade {
		err = stmt.QueryRow(start, end).Scan(&count)
		if err != nil {
			mlog.Fatalf("searchByYear:Unable to count rows: %s", err)
		}

		sql := fmt.Sprintf(`select rowid, title, original_title, file_title, year, runtime, tmdb_id, imdb_id, 
					overview, tagline, resolution, filetype, location, cover, backdrop, genres, vote_average, 
					vote_count, countries, added, modified, last_watched, all_watched, count_watched, score, 
					director, writer, actors, awards, imdb_rating, imdb_votes 
					from movie where year between ? and ? order by %s %s, rowid desc limit ? offset ?`, options.SortBy, options.SortOrder)

		stmt, err := tx.Prepare(sql)
		if err != nil {
			mlog.Fatalf("Unable to prepare transaction: %s", err)
		}
		defer stmt.Close()

		rows, err = stmt.Query(start, end, options.Limit, options.Offset)
		if err != nil {
			mlog.Fatalf("Unable to prepare transaction: %s", err)
		}
	} else {
		err = stmt.QueryRow(year).Scan(&count)
		if err != nil {
			mlog.Fatalf("searchByYear:Unable to count rows: %s", err)
		}

		sql := fmt.Sprintf(`select rowid, title, original_title, file_title, year, runtime, tmdb_id, imdb_id, 
					overview, tagline, resolution, filetype, location, cover, backdrop, genres, vote_average, 
					vote_count, countries, added, modified, last_watched, all_watched, count_watched, score, 
					director, writer, actors, awards, imdb_rating, imdb_votes 
					from movie where year = ? order by %s %s, rowid desc limit ? offset ?`, options.SortBy, options.SortOrder)

		mlog.Info("sql.: %s", sql)

		stmt, err := tx.Prepare(sql)
		if err != nil {
			mlog.Fatalf("Unable to prepare transaction: %s", err)
		}
		defer stmt.Close()

		rows, err = stmt.Query(year, options.Limit, options.Offset)
		if err != nil {
			mlog.Fatalf("Unable to prepare transaction: %s", err)
		}
	}

	items := make([]*model.Movie, 0)

	for rows.Next() {
		movie := model.Movie{}
		rows.Scan(
			&movie.Id, &movie.Title, &movie.Original_Title, &movie.File_Title, &movie.Year,
			&movie.Runtime, &movie.Tmdb_Id, &movie.Imdb_Id, &movie.Overview, &movie.Tagline,
			&movie.Resolution, &movie.FileType, &movie.Location, &movie.Cover, &movie.Backdrop,
			&movie.Genres, &movie.Vote_Average, &movie.Vote_Count, &movie.Production_Countries,
			&movie.Added, &movie.Modified, &movie.Last_Watched, &movie.All_Watched,
			&movie.Count_Watched, &movie.Score, &movie.Director, &movie.Writer, &movie.Actors,
			&movie.Awards, &movie.Imdb_Rating, &movie.Imdb_Votes,
		)
		// movie := &model.Movie{}
		// rows.Scan(movie.Id, movie.Title, movie.Original_Title, movie.Year, movie.Runtime, movie.Tmdb_Id, movie.Imdb_Id, movie.Overview, movie.Tagline, movie.Resolution, movie.FileType, movie.Location, movie.Cover, movie.Backdrop)
		// mlog.Info("title: (%s)", movie.Title)
		items = append(items, &movie)
		// mlog.Info("movie: %+v:", movie)
	}
	rows.Close()

	tx.Commit()

	mlog.Info("searchByYear:Listed %d movies (total %d)", len(items), count)

	return count, items
}
Пример #28
0
func Notify(bus *pubsub.PubSub, topic, text string) {
	mlog.Info(text)
	payload := &dto.Packet{Topic: topic, Payload: text}
	// payload := &dto.Packet{Topic: topic, Payload: text}
	bus.Pub(&pubsub.Message{Payload: payload}, "socket:connections:broadcast")
}
Пример #29
0
func (d *Dal) regularSearch(options *lib.Options) (total uint64, movies []*model.Movie) {
	mlog.Info("searchMovies.options: %+v", options)

	tx, err := d.db.Begin()
	if err != nil {
		mlog.Fatalf("searchMovies:Unable to begin transaction: %s", err)
	}

	term := options.Query + "*"
	args := options.FilterBy

	mlog.Info("this is: %s %s", term, args)

	// if self.searchArgs != args {
	// self.searchArgs = args

	countQuery := fmt.Sprintf(`select count(*) from movie dt, %s vt 
		where vt.%s match ? and dt.rowid = vt.docid;`,
		"movie"+options.FilterBy, "movie"+options.FilterBy)

	stmt, err := tx.Prepare(countQuery)
	if err != nil {
		mlog.Fatalf("searchMovies:Unable to prepare transaction: %s", err)
	}
	defer stmt.Close()

	mlog.Info("searchMovies:CountQuery:%s", countQuery)

	var count uint64
	err = stmt.QueryRow(term).Scan(&count)
	if err != nil {
		mlog.Fatalf("searchMovies:Unable to count rows: %s", err)
	}

	listQuery := fmt.Sprintf(`select dt.rowid, dt.title, dt.original_title, dt.year, dt.runtime, 
			dt.tmdb_id, dt.imdb_id, dt.overview, dt.tagline, dt.resolution, 
			dt.filetype, dt.location, dt.cover, dt.backdrop, dt.genres, dt.vote_average, 
			dt.vote_count, dt.countries, dt.added, dt.modified, dt.last_watched, 
			dt.all_watched, dt.count_watched, dt.score, dt.director, dt.writer, dt.actors, 
			dt.awards, dt.imdb_rating, dt.imdb_votes
			from movie dt, %s vt 
			where vt.%s match ? and dt.rowid = vt.docid order by dt.%s %s limit ? offset ?`,
		"movie"+options.FilterBy, "movie"+options.FilterBy, options.SortBy, options.SortOrder)

	// mlog.Info("my main man: %s", sql)

	stmt, err = tx.Prepare(listQuery)
	if err != nil {
		mlog.Fatalf("searchMovies:listQuery:Unable to prepare transaction: %s", err)
	}
	defer stmt.Close()

	rows, err := stmt.Query(term, options.Limit, options.Offset)
	if err != nil {
		mlog.Fatalf("searchMovies:listQuery:Unable to begin transaction: %s", err)
	}

	items := make([]*model.Movie, 0)

	for rows.Next() {
		movie := model.Movie{}
		rows.Scan(&movie.Id, &movie.Title, &movie.Original_Title, &movie.Year, &movie.Runtime, &movie.Tmdb_Id, &movie.Imdb_Id, &movie.Overview, &movie.Tagline, &movie.Resolution, &movie.FileType, &movie.Location, &movie.Cover, &movie.Backdrop, &movie.Genres, &movie.Vote_Average, &movie.Vote_Count, &movie.Production_Countries, &movie.Added, &movie.Modified, &movie.Last_Watched, &movie.All_Watched, &movie.Count_Watched, &movie.Score, &movie.Director, &movie.Writer, &movie.Actors, &movie.Awards, &movie.Imdb_Rating, &movie.Imdb_Votes)
		// movie := &model.Movie{}
		// rows.Scan(movie.Id, movie.Title, movie.Original_Title, movie.Year, movie.Runtime, movie.Tmdb_Id, movie.Imdb_Id, movie.Overview, movie.Tagline, movie.Resolution, movie.FileType, movie.Location, movie.Cover, movie.Backdrop)
		// mlog.Info("title: (%s)", movie.Title)
		items = append(items, &movie)
	}
	rows.Close()

	tx.Commit()

	mlog.Info("searchMovies:Listed %d movies (total %d)", len(items), count)

	return count, items
}