Skip to content

Commit

Permalink
refactor/ocp (#1)
Browse files Browse the repository at this point in the history
Co-authored-by: JarbasAi <[email protected]>
  • Loading branch information
NeonJarbas and JarbasAl authored Jan 8, 2024
1 parent f04c907 commit 7bcddd6
Show file tree
Hide file tree
Showing 7 changed files with 5,976 additions and 5,939 deletions.
11 changes: 1 addition & 10 deletions LICENSE
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]
Copyright 2024 Casimiro Ferreira

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -200,12 +200,3 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

=======================================================================

Component licenses for mycroft-core:

The mycroft-core software references various Python Packages (via PIP),
each of which has a separate license. All are compatible with the
Apache 2.0 license. See the referenced packages listed in the
"requirements/requirements.txt" file for specific terms and conditions.
175 changes: 114 additions & 61 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,66 @@
from os.path import join, dirname
import random
from os.path import join, dirname

from ovos_plugin_common_play.ocp import MediaType, PlaybackType
from ovos_utils.log import LOG
from ovos_utils.parse import fuzzy_match
from ovos_workshop.skills.common_play import OVOSCommonPlaybackSkill, \
ocp_search, ocp_featured_media
from youtube_archivist import YoutubeMonitor
import requests
from json_database import JsonStorageXDG

from ovos_utils.ocp import MediaType, PlaybackType
from ovos_workshop.decorators.ocp import ocp_search, ocp_featured_media
from ovos_workshop.skills.common_play import OVOSCommonPlaybackSkill


class FullFreeFilmsSkill(OVOSCommonPlaybackSkill):
def __init__(self):
super().__init__("FullFreeFilms")
self.supported_media = [MediaType.MOVIE,
MediaType.GENERIC]
def __init__(self, *args, **kwargs):
self.supported_media = [MediaType.MOVIE]
self.skill_icon = self.default_bg = join(dirname(__file__), "ui", "fff_logo.png")
self.archive = YoutubeMonitor(db_name="FullFreeFilms",
min_duration=30 * 60,
logger=LOG,
blacklisted_kwords=["trailer", "teaser", "movie scene",
"movie clip", "behind the scenes",
"Movie Preview"])
self.archive = JsonStorageXDG("FullFreeFilms", subfolder="OCP")
self.media_type_exceptions = {}
super().__init__(*args, **kwargs)

def initialize(self):
bootstrap = "https://github.com/JarbasSkills/skill-fff/raw/dev/bootstrap.json"
self.archive.bootstrap_from_url(bootstrap)
self.schedule_event(self._sync_db, random.randint(3600, 24 * 3600))
self._sync_db()
self.load_ocp_keywords()

def load_ocp_keywords(self):
genre = ["horror", "scifi", "sci-fi", "action", "fantasy"]
title = []
docus = []

for url, data in self.archive.items():
t = data["title"].split("|")[0].split("(")[0].strip().strip("¿?.!").rstrip("¿")
if "documentary" in data["title"].lower():
docus.append(t)
if ":" in t:
t1, t2 = t.split(":", 1)
docus.append(t1.strip())
docus.append(t2.strip())
# signal this entry as DOCUMENTARY media type
# in case it gets selected later
self.media_type_exceptions[data["url"]] = MediaType.DOCUMENTARY
else:
title.append(t)
if ":" in t:
t1, t2 = t.split(":", 1)
title.append(t1.strip())
title.append(t2.strip())

self.register_ocp_keyword(MediaType.MOVIE,
"movie_name", title)
self.register_ocp_keyword(MediaType.DOCUMENTARY,
"documentary_name", docus)
self.register_ocp_keyword(MediaType.MOVIE,
"film_genre", genre)
self.register_ocp_keyword(MediaType.MOVIE,
"movie_streaming_provider",
["Full Free Films",
"FFF",
"FullFreeFilms"])

def _sync_db(self):
url = "https://www.youtube.com/channel/UCqBi1RfMbdXES6t2iMaIYSA"
self.archive.parse_videos(url)
self.schedule_event(self._sync_db, random.randint(3600, 24*3600))

# matching
def match_skill(self, phrase, media_type):
score = 0
if self.voc_match(phrase, "movie") or media_type == MediaType.MOVIE:
score += 10
if self.voc_match(phrase, "fff"):
score += 50
return score

def normalize_title(self, title):
title = title.lower().strip()
title = self.remove_voc(title, "fff")
title = self.remove_voc(title, "movie")
title = title.replace("|", "").replace('"', "") \
.replace(':', "").replace('”', "").replace('“', "") \
.strip()
return " ".join(
[w for w in title.split(" ") if w]) # remove extra spaces

def calc_score(self, phrase, match, base_score=0):
score = base_score
score += 100 * fuzzy_match(phrase.lower(), match["title"].lower())
return min(100, score)
bootstrap = "https://github.com/JarbasSkills/skill-fff/raw/dev/bootstrap.json"
data = requests.get(bootstrap).json()
self.archive.merge(data)
self.schedule_event(self._sync_db, random.randint(3600, 24 * 3600))

def get_playlist(self, score=50, num_entries=250):
pl = self.featured_media()[:num_entries]
Expand All @@ -72,26 +78,63 @@ def get_playlist(self, score=50, num_entries=250):

@ocp_search()
def search_db(self, phrase, media_type):
base_score = self.match_skill(phrase, media_type)
if self.voc_match(phrase, "fff"):
yield self.get_playlist(base_score)
if media_type == MediaType.MOVIE:
# only search db if user explicitly requested movies
phrase = self.normalize_title(phrase)
for url, video in self.archive.db.items():
base_score = 15 if media_type == MediaType.MOVIE else 0
entities = self.ocp_voc_match(phrase)

skill = "movie_streaming_provider" in entities # skill matched

base_score += 30 * len(entities)
title = entities.get("movie_name")
dtitle = entities.get("documentary_name")

if media_type == MediaType.DOCUMENTARY:
candidates = [video for video in self.archive.values()
if self.media_type_exceptions.get(video["url"], MediaType.MOVIE) ==
MediaType.DOCUMENTARY]

else:
candidates = [video for video in self.archive.values()
if video["url"] not in self.media_type_exceptions]

if title:
base_score += 30
candidates = [video for video in candidates
if title.lower() in video["title"].lower()]
for video in candidates:
yield {
"title": video["title"],
"author": "Full Free Films",
"match_confidence": self.calc_score(phrase, video, base_score),
"author": video["author"],
"match_confidence": min(100, base_score),
"media_type": MediaType.MOVIE,
"uri": "youtube//" + url,
"uri": "youtube//" + video["url"],
"playback": PlaybackType.VIDEO,
"skill_icon": self.skill_icon,
"skill_id": self.skill_id,
"image": video["thumbnail"],
"bg_image": self.default_bg
"bg_image": video["thumbnail"]
}

if dtitle:
base_score += 20
candidates = [video for video in candidates
if dtitle.lower() in video["title"].lower()]
for video in candidates:
yield {
"title": video["title"],
"author": video["author"],
"match_confidence": min(100, base_score),
"media_type": MediaType.DOCUMENTARY,
"uri": "youtube//" + video["url"],
"playback": PlaybackType.VIDEO,
"skill_icon": self.skill_icon,
"skill_id": self.skill_id,
"image": video["thumbnail"],
"bg_image": video["thumbnail"]
}

if skill:
yield self.get_playlist()

@ocp_featured_media()
def featured_media(self):
return [{
Expand All @@ -104,8 +147,18 @@ def featured_media(self):
"skill_icon": self.skill_icon,
"bg_image": video["thumbnail"],
"skill_id": self.skill_id
} for video in self.archive.sorted_entries()]
} for video in self.archive.values()]


if __name__ == "__main__":
from ovos_utils.messagebus import FakeBus

s = FullFreeFilmsSkill(bus=FakeBus(), skill_id="t.fake")
for r in s.search_db("play THE BODY TREE", MediaType.MOVIE):
print(r)
# {'title': 'THE BODY TREE | Full HORROR Movie | MURDER MYSTERY', 'author': 'FFF Full Free Films', 'match_confidence': 75, 'media_type': <MediaType.MOVIE: 10>, 'uri': 'youtube//https://youtube.com/watch?v=uqJDLazlrPg', 'playback': <PlaybackType.VIDEO: 1>, 'skill_icon': 'https://github.com/OpenVoiceOS/ovos-ocp-audio-plugin/raw/master/ovos_plugin_common_play/ocp/res/ui/images/ocp.png', 'skill_id': 't.fake', 'image': 'https://i.ytimg.com/vi/uqJDLazlrPg/sddefault.jpg', 'bg_image': 'https://i.ytimg.com/vi/uqJDLazlrPg/sddefault.jpg'}

def create_skill():
return FullFreeFilmsSkill()
for r in s.search_db("play ZEITGEIST", MediaType.DOCUMENTARY):
print(r)
# {'title': 'ZEITGEIST: MOVING FORWARD | Full Documentary Movie | The Monetary-Market Economics Explained', 'author': 'FFF Full Free Films', 'match_confidence': 50, 'media_type': <MediaType.DOCUMENTARY: 15>, 'uri': 'youtube//https://youtube.com/watch?v=BOQtgMpSEFM', 'playback': <PlaybackType.VIDEO: 1>, 'skill_icon': 'https://github.com/OpenVoiceOS/ovos-ocp-audio-plugin/raw/master/ovos_plugin_common_play/ocp/res/ui/images/ocp.png', 'skill_id': 't.fake', 'image': 'https://i.ytimg.com/vi/BOQtgMpSEFM/sddefault.jpg?v=605a6f05', 'bg_image': 'https://i.ytimg.com/vi/BOQtgMpSEFM/sddefault.jpg?v=605a6f05'}
# {'title': 'ZEITGEIST THE MOVIE: ADDENDUM | The Economic Corruption Explained | Full Documentary', 'author': 'FFF Full Free Films', 'match_confidence': 50, 'media_type': <MediaType.DOCUMENTARY: 15>, 'uri': 'youtube//https://youtube.com/watch?v=AttPOn1ZOfk', 'playback': <PlaybackType.VIDEO: 1>, 'skill_icon': 'https://github.com/OpenVoiceOS/ovos-ocp-audio-plugin/raw/master/ovos_plugin_common_play/ocp/res/ui/images/ocp.png', 'skill_id': 't.fake', 'image': 'https://i.ytimg.com/vi/AttPOn1ZOfk/sddefault.jpg?v=60662369', 'bg_image': 'https://i.ytimg.com/vi/AttPOn1ZOfk/sddefault.jpg?v=60662369'}
Loading

0 comments on commit 7bcddd6

Please sign in to comment.