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() }
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") }
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 }
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") }
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() }
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 } } }
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() }
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) }
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 }
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() }
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} }
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") }
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} }
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() }
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 }
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") } }
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) }
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 } } } }
func (c *Core) Stop() { mlog.Info("Stopped service Core ...") }
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() }
func (d *Dal) Stop() { mlog.Info("Stopped service Dal ...") }
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 }
func (c *Core) getConfig(msg *pubsub.Message) { msg.Reply <- &c.settings.Config mlog.Info("Sent config") }
func (c *Cache) Stop() { mlog.Info("Stopped service Cache") }
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 // } }
func (s *Scanner) Stop() { mlog.Info("Stopped service Scanner ...") }
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 }
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") }
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 }