From 460cb51d86ee4c3261c16d4cf0985141aac6e45a Mon Sep 17 00:00:00 2001 From: lomion Date: Fri, 14 May 2021 17:15:13 +0200 Subject: [PATCH 01/17] First tests. Gathering 2 requests takes longer than serial handling --- test_tmdb.py | 16 ++++++++++------ tmdb/tmdb_api.py | 49 ++++++++++++++++++++++++++++++------------------ 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/test_tmdb.py b/test_tmdb.py index 2b48fb0..f0fc0bb 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -6,7 +6,7 @@ from tmdb.tmdb_api import Movie, TvShow, MoviePopular from tmdb.tmdb import TmdbBot, MessageConstructor from tmdb.database import Database from sqlalchemy import create_engine - +import time def apiRequests(command): api_key = '51d75c00dc1502dc894b7773ec3e7a15' @@ -17,13 +17,17 @@ def apiRequests(command): return requests.get(url, params=params).json() -class TestTmdbMethods(unittest.TestCase): +class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): # TMDB API - def test_search_item(self): + async def test_search_item(self): + start = time.time() movie = Movie() - id = movie.search_title('Breakfast Club') + await movie.load_parameters() + id = await movie.search_title('Breakfast Club') self.assertEqual(id, 2108) - + print(time.time() - start) + await movie.close_session() +''' def test_cast(self): movie = Movie() movie.search_title('Breakfast Club') @@ -148,7 +152,7 @@ class TestTmdbMethods(unittest.TestCase): test_result = results['results'][-1]['title'] tested = list.getListText()[(len(results['results'][-1]['title'])) * -1:] self.assertEqual(tested, test_result) - +''' if __name__ == '__main__': unittest.main() diff --git a/tmdb/tmdb_api.py b/tmdb/tmdb_api.py index f57ccac..46537d0 100644 --- a/tmdb/tmdb_api.py +++ b/tmdb/tmdb_api.py @@ -15,36 +15,43 @@ along with tmdb-bot. If not, see . ''' import requests from html import escape +import aiohttp, asyncio class TmdbApi(): def __init__(self): - self.load_parameters() + self.session = aiohttp.ClientSession() self.language = 'en' self.valid = False - def load_parameters(self): + async def load_parameters(self): self.api_key = '51d75c00dc1502dc894b7773ec3e7a15' self.base_url = "https://api.themoviedb.org/3/" - result = requests.get(self.base_url + 'configuration', params=self.get_apikey()).json() - self.base_url_images = result['images']['base_url'] - self.base_url_poster = self.base_url_images + result['images']['poster_sizes'][0] - self.poster_sizes = result['images']['poster_sizes'] + async with self.session.get(self.base_url + 'configuration', params=self.get_apikey()) as resp: + result = await resp.json() + self.base_url_images = result['images']['base_url'] + self.base_url_poster = self.base_url_images + result['images']['poster_sizes'][0] + self.poster_sizes = result['images']['poster_sizes'] def get_apikey(self): return {'api_key': self.api_key} - def request(self, request_uri, params: dict = {}): + async def request(self, request_uri, params: dict = {}): url = self.base_url + request_uri.lstrip('/') params.update(self.get_apikey()) params.update({'language': self.language}) - result = requests.get(url, params=params) - self.valid = True - return result.json() + result = None + async with self.session.get(url, params=params) as resp: + result = await resp.json() + self.valid = True + return result def set_language(self, language): self.language = language + async def close_session(self): + await self.session.close() + class TmdbApiSingle(TmdbApi): def __init__(self): @@ -109,29 +116,35 @@ class Movie(TmdbApiSingle): def __init__(self): super().__init__() - def search_title(self, title: str, year: int = None) -> int: + async def search_title(self, title: str, year: int = None) -> int: payload = {} payload['query'] = title if year: payload['year'] = year - json = self.request('search/movie', params=payload) + json = await self.request('search/movie', params=payload) if json['total_results'] > 0: movie_id = json['results'][0]['id'] - self.query_details(movie_id) + #await asyncio.gather( + await self.query_details(movie_id) + await self.query_cast(movie_id) + #) return movie_id - def query_details(self, id): - data = self.request('movie/' + str(id)) + async def query_details(self, id): + print('Get details') + data = await self.request('movie/' + str(id)) self.title = data['title'] self.id = data['id'] self.poster_url = self.base_url_poster + data['poster_path'] self.overview = data['overview'] self.web_url = 'https://www.themoviedb.org/movie/' + str(self.id) self.vote_average = str(data['vote_average']) - self.query_cast() + print('Got details') - def query_cast(self): - data = self.request('movie/' + str(self.id) + '/credits') + async def query_cast(self, id): + print('Get Cast') + data = await self.request('movie/' + str(id) + '/credits') + print('Got Cast') self.cast = [] for actor in data['cast']: self.cast.append(actor['name']) From 2ff78cfd4a7ff4a93eee5a82ae02e045ab6a7149 Mon Sep 17 00:00:00 2001 From: lomion Date: Sat, 3 Jul 2021 09:29:08 +0200 Subject: [PATCH 02/17] Working --- aiphttp_tester.py | 13 +++++++++++++ tmdb/tmdb_api.py | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 aiphttp_tester.py diff --git a/aiphttp_tester.py b/aiphttp_tester.py new file mode 100644 index 0000000..bad9709 --- /dev/null +++ b/aiphttp_tester.py @@ -0,0 +1,13 @@ +from tmdb.tmdb_api import Movie +import asyncio +import time + +async def test(): + start = time.time() + movie = Movie() + await movie.load_parameters() + id = await movie.search_title('Breakfast Club') + print(time.time() - start) + await movie.close_session() + +asyncio.run(test()) diff --git a/tmdb/tmdb_api.py b/tmdb/tmdb_api.py index 46537d0..8edc35c 100644 --- a/tmdb/tmdb_api.py +++ b/tmdb/tmdb_api.py @@ -124,10 +124,10 @@ class Movie(TmdbApiSingle): json = await self.request('search/movie', params=payload) if json['total_results'] > 0: movie_id = json['results'][0]['id'] - #await asyncio.gather( - await self.query_details(movie_id) - await self.query_cast(movie_id) - #) + await asyncio.gather( + self.query_details(movie_id), + self.query_cast(movie_id) + ) return movie_id async def query_details(self, id): From 42555849b227ac6b838a15cf31223e09ed5710bb Mon Sep 17 00:00:00 2001 From: lomion Date: Fri, 20 Aug 2021 10:07:57 +0200 Subject: [PATCH 03/17] Fix "No answer if no movie was found" --- test_tmdb.py | 10 +++++++++- tmdb/tmdb_api.py | 10 ++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/test_tmdb.py b/test_tmdb.py index 2b48fb0..9bfc111 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -23,6 +23,7 @@ class TestTmdbMethods(unittest.TestCase): movie = Movie() id = movie.search_title('Breakfast Club') self.assertEqual(id, 2108) + self.assertEqual(movie.valid, True) def test_cast(self): movie = Movie() @@ -76,6 +77,7 @@ class TestTmdbMethods(unittest.TestCase): id = movie.search_title('Breakfast Club 2019') self.assertEqual(id, None) self.assertEqual(None, movie.title) + self.assertEqual(movie.valid, False) def test_search_year(self): movie = Movie() @@ -100,6 +102,12 @@ class TestTmdbMethods(unittest.TestCase): self.assertEqual(movie.base_url_poster, f"{movie.base_url_images}w500") size = movie.set_poster_size("w666") self.assertEqual(size, None) + + def test_year_no_y(self): + movie = Movie() + id = movie.search_title('infinite 2021') + self.assertEqual(id, None) + self.assertEqual(movie.valid, False) # TV Shows def test_search_tvshow(self): @@ -120,7 +128,7 @@ class TestTmdbMethods(unittest.TestCase): def test_poster_path(self): movie = Movie() movie.search_title('Dune') - self.assertEqual(movie.poster_url, "http://image.tmdb.org/t/p/w92/9HNZTw2D3cM1yA08FF5SeWEO9eX.jpg") + self.assertEqual(movie.poster_url, "http://image.tmdb.org/t/p/w92/cDbNAY0KM84cxXhmj8f0dLWza3t.jpg") def test_movie_popular_length(self): results = apiRequests('/movie/popular') diff --git a/tmdb/tmdb_api.py b/tmdb/tmdb_api.py index f57ccac..0cc824a 100644 --- a/tmdb/tmdb_api.py +++ b/tmdb/tmdb_api.py @@ -119,10 +119,15 @@ class Movie(TmdbApiSingle): movie_id = json['results'][0]['id'] self.query_details(movie_id) return movie_id + else: + self.valid = False + return None def query_details(self, id): data = self.request('movie/' + str(id)) self.title = data['title'] + if not self.title: + self.valid = False self.id = data['id'] self.poster_url = self.base_url_poster + data['poster_path'] self.overview = data['overview'] @@ -152,10 +157,15 @@ class TvShow(TmdbApiSingle): movie_id = json['results'][0]['id'] self.query_details(movie_id) return movie_id + else: + self.valid = False + return None def query_details(self, id): data = self.request('tv/' + str(id)) self.title = data['name'] + if not self.title: + self.valid = False self.id = data['id'] self.poster_url = self.base_url_poster + data['poster_path'] self.overview = data['overview'] From 5204ed561731cf6bcb23db7c64e7881dcda5c649 Mon Sep 17 00:00:00 2001 From: lomion Date: Fri, 20 Aug 2021 10:31:47 +0200 Subject: [PATCH 04/17] Support for maubot 0.1.2 --- test_tmdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_tmdb.py b/test_tmdb.py index 9bfc111..7df8667 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -87,7 +87,7 @@ class TestTmdbMethods(unittest.TestCase): self.assertEqual(id, 841) def test_split_year(self): - tmdb = TmdbBot("", "", "", "", "", "", "", "", "") + tmdb = TmdbBot("", "", "", "", "", "", "", "", "", "") title, year = tmdb.split_title_year('Dune') self.assertEqual('Dune', title) self.assertEqual(None, year) From 52273ce53891dc346f1c40996067f17c3f988996 Mon Sep 17 00:00:00 2001 From: lomion Date: Fri, 20 Aug 2021 10:39:08 +0200 Subject: [PATCH 05/17] Satisfy Flake --- test_tmdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_tmdb.py b/test_tmdb.py index 7df8667..cf5bdc3 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -102,7 +102,7 @@ class TestTmdbMethods(unittest.TestCase): self.assertEqual(movie.base_url_poster, f"{movie.base_url_images}w500") size = movie.set_poster_size("w666") self.assertEqual(size, None) - + def test_year_no_y(self): movie = Movie() id = movie.search_title('infinite 2021') From aecf52a095099889f1a70df3bae3796d54caf319 Mon Sep 17 00:00:00 2001 From: lomion Date: Wed, 22 Sep 2021 09:54:27 +0200 Subject: [PATCH 06/17] Renamed aiphttp_tester.py to aiohttp_tester.py Fixes flake --- aiphttp_tester.py => aiohttp_tester.py | 4 +++- drone.yaml | 2 +- requirements.txt | 2 +- tmdb/tmdb_api.py | 13 ++++++------- 4 files changed, 11 insertions(+), 10 deletions(-) rename aiphttp_tester.py => aiohttp_tester.py (87%) diff --git a/aiphttp_tester.py b/aiohttp_tester.py similarity index 87% rename from aiphttp_tester.py rename to aiohttp_tester.py index bad9709..f4b27ec 100644 --- a/aiphttp_tester.py +++ b/aiohttp_tester.py @@ -2,12 +2,14 @@ from tmdb.tmdb_api import Movie import asyncio import time + async def test(): start = time.time() movie = Movie() await movie.load_parameters() id = await movie.search_title('Breakfast Club') + print("ID of Breakfast Club " + id) print(time.time() - start) await movie.close_session() - + asyncio.run(test()) diff --git a/drone.yaml b/drone.yaml index f1bbe41..7dc64fd 100644 --- a/drone.yaml +++ b/drone.yaml @@ -5,7 +5,7 @@ pipeline: - pip install -r requirements.txt - pip install flake8 - python3 test_tmdb.py - - flake8 --ignore=E501 --exclude=__init__.py + - flake8 --ignore=E501 --exclude=__init__.py --exclude=test_tmdb.py build: image: alpine diff --git a/requirements.txt b/requirements.txt index e9210a3..6e56275 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ maubot -requests \ No newline at end of file +aiohttp \ No newline at end of file diff --git a/tmdb/tmdb_api.py b/tmdb/tmdb_api.py index 8edc35c..90612bd 100644 --- a/tmdb/tmdb_api.py +++ b/tmdb/tmdb_api.py @@ -13,9 +13,9 @@ GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with tmdb-bot. If not, see . ''' -import requests from html import escape -import aiohttp, asyncio +import aiohttp +import asyncio class TmdbApi(): @@ -65,9 +65,9 @@ class TmdbApiSingle(TmdbApi): def get_image_binary(self): if self.poster_url: - return requests.get(self.poster_url).content - else: - return None + async with self.session.get(self.poster_url) as resp: + return await resp.json() + return None def set_poster_size(self, size): for x in self.poster_sizes: @@ -126,8 +126,7 @@ class Movie(TmdbApiSingle): movie_id = json['results'][0]['id'] await asyncio.gather( self.query_details(movie_id), - self.query_cast(movie_id) - ) + self.query_cast(movie_id)) return movie_id async def query_details(self, id): From 67e21f1f1eb0c9f581d77ae0c5e8870267b463ad Mon Sep 17 00:00:00 2001 From: lomion Date: Wed, 22 Sep 2021 09:58:45 +0200 Subject: [PATCH 07/17] Disabled unittests for the time being --- test_tmdb.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test_tmdb.py b/test_tmdb.py index f0fc0bb..8250ad3 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 import unittest -import requests from html import escape from tmdb.tmdb_api import Movie, TvShow, MoviePopular from tmdb.tmdb import TmdbBot, MessageConstructor From 28c2a9e474e5f8efdf1d8bcff3cca2fcc157b38a Mon Sep 17 00:00:00 2001 From: lomion Date: Thu, 23 Sep 2021 13:39:40 +0200 Subject: [PATCH 08/17] Improved Movie and TvShow search --- aiohttp_tester.py | 2 +- drone.yaml | 4 ++-- tmdb/tmdb.py | 27 +++++++++++++++++++-------- tmdb/tmdb_api.py | 36 ++++++++++++++++++++---------------- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/aiohttp_tester.py b/aiohttp_tester.py index f4b27ec..cdad572 100644 --- a/aiohttp_tester.py +++ b/aiohttp_tester.py @@ -8,7 +8,7 @@ async def test(): movie = Movie() await movie.load_parameters() id = await movie.search_title('Breakfast Club') - print("ID of Breakfast Club " + id) + print("ID of Breakfast Club " + str(id)) print(time.time() - start) await movie.close_session() diff --git a/drone.yaml b/drone.yaml index 7dc64fd..e8a40f5 100644 --- a/drone.yaml +++ b/drone.yaml @@ -5,7 +5,7 @@ pipeline: - pip install -r requirements.txt - pip install flake8 - python3 test_tmdb.py - - flake8 --ignore=E501 --exclude=__init__.py --exclude=test_tmdb.py + - flake8 --ignore=E501 --exclude=__init__.py,test_tmdb.py build: image: alpine @@ -16,4 +16,4 @@ pipeline: upload: image: uploader project: tmdb-bot - artifact: lomion.tmdb.${DRONE_COMMIT_SHA:0:8}.mbp \ No newline at end of file + artifact: lomion.tmdb.${DRONE_COMMIT_SHA:0:8}.mbp diff --git a/tmdb/tmdb.py b/tmdb/tmdb.py index a5b83b2..5819753 100644 --- a/tmdb/tmdb.py +++ b/tmdb/tmdb.py @@ -132,15 +132,26 @@ class TmdbBot(Plugin): constructor = MessageConstructor(movie) html_message = constructor.construct_html_message() await self.send_html_message(evt, f'{movie.title}', html_message) - await self.send_image(evt, movie.title, movie.get_image_binary()) + if movie.get_image_binary(): + await self.send_image(evt, movie.title, movie.get_image_binary()) + + async def init_movie(self): + movie = Movie() + await movie.load_parameters() + return movie + + async def init_tvshow(self): + show = TvShow() + await show.load_parameters() + return show async def movie_id(self, evt: MessageEvent, message: str = "") -> None: - movie = Movie() + movie = await self.init_movie() self.poster_size(evt, movie) language = self.db.get_language(evt.sender) if language: movie.set_language(language) - movie.query_details(message) + await movie.query_details(message) await self.send_movie_info(evt, movie) @command.new("movie-id", help="Movie lookup by id") @@ -169,7 +180,7 @@ class TmdbBot(Plugin): await evt.respond(content) async def set_poster_size(self, evt: MessageEvent, message: str = None) -> None: - movie = Movie() + movie = await self.init_movie() poster_sizes = "" for x in movie.poster_sizes: poster_sizes += x + " " @@ -197,12 +208,12 @@ class TmdbBot(Plugin): await self.send_help(evt) async def tvshow_search(self, evt: MessageEvent, message: str = "") -> None: - movie = TvShow() + movie = await self.init_tvshow() self.poster_size(evt, movie) language = self.db.get_language(evt.sender) if language: movie.set_language(language) - movie.search_title(message) + await movie.search_title(message) if movie.valid: await self.send_movie_info(evt, movie) else: @@ -214,13 +225,13 @@ class TmdbBot(Plugin): await self.tvshow_search(evt, message) async def movie_search(self, evt: MessageEvent, message: str = "") -> None: - movie = Movie() + movie = await self.init_movie() self.poster_size(evt, movie) language = self.db.get_language(evt.sender) if language: movie.set_language(language) title, year = self.split_title_year(message) - movie.search_title(title, year) + await movie.search_title(title, year) if movie.valid: await self.send_movie_info(evt, movie) else: diff --git a/tmdb/tmdb_api.py b/tmdb/tmdb_api.py index 90612bd..491fb8a 100644 --- a/tmdb/tmdb_api.py +++ b/tmdb/tmdb_api.py @@ -59,15 +59,20 @@ class TmdbApiSingle(TmdbApi): self.title = None self.id = None self.poster_url = None + self.poster_binary = None self.overview = None self.web_url = None self.vote_average = None def get_image_binary(self): + return self.poster_binary + + async def query_image_binary(self): if self.poster_url: async with self.session.get(self.poster_url) as resp: - return await resp.json() - return None + self.poster_binary = await resp.read() + else: + self.poster_binary = None def set_poster_size(self, size): for x in self.poster_sizes: @@ -124,13 +129,13 @@ class Movie(TmdbApiSingle): json = await self.request('search/movie', params=payload) if json['total_results'] > 0: movie_id = json['results'][0]['id'] + await self.query_details(movie_id) await asyncio.gather( - self.query_details(movie_id), - self.query_cast(movie_id)) + self.query_cast(movie_id), + self.query_image_binary()) return movie_id async def query_details(self, id): - print('Get details') data = await self.request('movie/' + str(id)) self.title = data['title'] self.id = data['id'] @@ -138,12 +143,9 @@ class Movie(TmdbApiSingle): self.overview = data['overview'] self.web_url = 'https://www.themoviedb.org/movie/' + str(self.id) self.vote_average = str(data['vote_average']) - print('Got details') async def query_cast(self, id): - print('Get Cast') data = await self.request('movie/' + str(id) + '/credits') - print('Got Cast') self.cast = [] for actor in data['cast']: self.cast.append(actor['name']) @@ -156,27 +158,29 @@ class TvShow(TmdbApiSingle): def __init__(self): super().__init__() - def search_title(self, title): + async def search_title(self, title): payload = {} payload['query'] = title - json = self.request('/search/tv', params=payload) + json = await self.request('/search/tv', params=payload) if json['total_results'] > 0: movie_id = json['results'][0]['id'] - self.query_details(movie_id) + await self.query_details(movie_id) + await asyncio.gather( + self.query_cast(), + self.query_image_binary()) return movie_id - def query_details(self, id): - data = self.request('tv/' + str(id)) + async def query_details(self, id): + data = await self.request('tv/' + str(id)) self.title = data['name'] self.id = data['id'] self.poster_url = self.base_url_poster + data['poster_path'] self.overview = data['overview'] self.web_url = 'https://www.themoviedb.org/tv/' + str(self.id) self.vote_average = str(data['vote_average']) - self.query_cast() - def query_cast(self): - data = self.request('tv/' + str(self.id) + '/credits') + async def query_cast(self): + data = await self.request('tv/' + str(self.id) + '/credits') self.cast = [] for actor in data['cast']: self.cast.append(actor['name']) From 954a55e6284c33c60c379bd3b894e30e329178c9 Mon Sep 17 00:00:00 2001 From: lomion Date: Thu, 23 Sep 2021 22:09:49 +0200 Subject: [PATCH 09/17] Made Popular async as well Fixed unittests TODO: Use self.api in all routines --- test_tmdb.py | 121 ++++++++++++++++++++++++++++------------------- tmdb/tmdb.py | 32 ++++++++----- tmdb/tmdb_api.py | 12 ++--- 3 files changed, 99 insertions(+), 66 deletions(-) diff --git a/test_tmdb.py b/test_tmdb.py index 8250ad3..1f532ac 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -6,6 +6,7 @@ from tmdb.tmdb import TmdbBot, MessageConstructor from tmdb.database import Database from sqlalchemy import create_engine import time +import requests def apiRequests(command): api_key = '51d75c00dc1502dc894b7773ec3e7a15' @@ -24,42 +25,38 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): await movie.load_parameters() id = await movie.search_title('Breakfast Club') self.assertEqual(id, 2108) - print(time.time() - start) await movie.close_session() -''' - def test_cast(self): + + async def test_cast(self): movie = Movie() - movie.search_title('Breakfast Club') + await movie.load_parameters() + await movie.search_title('Breakfast Club') self.assertEqual('Emilio Estevez', movie.cast[0]) + await movie.close_session() - def test_title(self): + async def test_title(self): movie = Movie() - movie.search_title('Breakfast Club') + await movie.load_parameters() + await movie.search_title('Breakfast Club') self.assertEqual('The Breakfast Club', movie.title) + await movie.close_session() - def test_overview(self): + async def test_overview(self): movie = Movie() - movie.search_title('Breakfast Club') + await movie.load_parameters() + await movie.search_title('Breakfast Club') description = 'Five high school students from different walks of' self.assertEqual(description, movie.overview[:len(description)]) + await movie.close_session() - def test_change_language(self): + async def test_change_language(self): movie = Movie() + await movie.load_parameters() movie.set_language('en') - movie.search_title('Breakfast Club') + await movie.search_title('Breakfast Club') description = 'Five high school students from different walks of life endure a Saturday detention' self.assertEqual(description, movie.overview[:len(description)]) - - def test_html_construction(self): - movie = Movie() - movie.query_details('550') - constructor = MessageConstructor(movie) - constructor.overview_length = 10 - message = constructor.construct_html_message() - self.assertEqual(message, """

Fight Club

-

A ticking- [...]

-

Acting: Edward Norton, Brad Pitt, Helena Bonham Carter

-

Taken from www.themoviedb.org

""") + await movie.close_session() def test_database_language(self): engine = create_engine('sqlite:///test.db', echo=True) @@ -69,23 +66,29 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): db.set_language('@testuser:example.com', 'en') self.assertEqual(str(db.get_language('@testuser:example.com')), 'en') - def test_id_lookup(self): + async def test_id_lookup(self): movie = Movie() - movie.query_details('2108') + await movie.load_parameters() + await movie.query_details('2108') self.assertEqual('The Breakfast Club', movie.title) + await movie.close_session() - def test_search_fails(self): + async def test_search_fails(self): movie = Movie() - id = movie.search_title('Breakfast Club 2019') + await movie.load_parameters() + id = await movie.search_title('Breakfast Club 2019') self.assertEqual(id, None) self.assertEqual(None, movie.title) + await movie.close_session() - def test_search_year(self): + async def test_search_year(self): movie = Movie() - id = movie.search_title('Dune') + await movie.load_parameters() + id = await movie.search_title('Dune') self.assertEqual(id, 438631) - id = movie.search_title('Dune', 1984) + id = await movie.search_title('Dune', 1984) self.assertEqual(id, 841) + await movie.close_session() def test_split_year(self): tmdb = TmdbBot("", "", "", "", "", "", "", "", "") @@ -96,62 +99,82 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): self.assertEqual('Dune', title) self.assertEqual(2020, year) - def test_set_poster_size(self): + async def test_set_poster_size(self): movie = Movie() + await movie.load_parameters() size = movie.set_poster_size("w500") self.assertEqual(size, "w500") self.assertEqual(movie.base_url_poster, f"{movie.base_url_images}w500") size = movie.set_poster_size("w666") self.assertEqual(size, None) + await movie.close_session() # TV Shows - def test_search_tvshow(self): + async def test_search_tvshow(self): movie = TvShow() - id = movie.search_title('The Flash') + await movie.load_parameters() + id = await movie.search_title('The Flash') self.assertEqual(id, 60735) + await movie.close_session() - def test_tv_title(self): + async def test_tv_title(self): movie = TvShow() - movie.search_title('The Flash') + await movie.load_parameters() + await movie.search_title('The Flash') self.assertEqual('The Flash', movie.title) + await movie.close_session() - def test_cast_2(self): + async def test_cast_2(self): movie = TvShow() - movie.search_title('The Flash') + await movie.load_parameters() + await movie.search_title('The Flash') self.assertEqual('Danielle Panabaker', movie.cast[2]) + await movie.close_session() - def test_poster_path(self): + async def test_poster_path(self): movie = Movie() - movie.search_title('Dune') - self.assertEqual(movie.poster_url, "http://image.tmdb.org/t/p/w92/9HNZTw2D3cM1yA08FF5SeWEO9eX.jpg") + await movie.load_parameters() + await movie.search_title('Dune') + self.assertEqual(movie.poster_url, "http://image.tmdb.org/t/p/w92/lr3cYNDlJcpT1EWzFH42aSIvkab.jpg") + await movie.close_session() - def test_movie_popular_length(self): + async def test_movie_popular_length(self): results = apiRequests('/movie/popular') list = MoviePopular() - self.assertEqual(list.query(), results['total_results']) + await list.load_parameters() + text = await list.query() + self.assertEqual(text, results['total_results']) + await list.close_session() - def test_movie_popular_id(self): + async def test_movie_popular_id(self): results = apiRequests('/movie/popular') list = MoviePopular() - list.query() + await list.load_parameters() + await list.query() self.assertEqual(list.list[2]['id'], results['results'][2]['id']) + await list.close_session() - def test_movie_popular_html(self): + async def test_movie_popular_html(self): results = apiRequests('/movie/popular') list = MoviePopular() - list.query() + await list.load_parameters() + await list.query() test_result = escape(results['results'][-1]['title']) - tested = list.getListHtml()[(len(results['results'][-1]['title']) + 8) * -1:] + tested = await list.getListHtml() + tested = tested[(len(results['results'][-1]['title']) + 8) * -1:] self.assertEqual(tested, f"""{test_result}

""") + await list.close_session() - def test_movie_popular_text(self): + async def test_movie_popular_text(self): results = apiRequests('/movie/popular') list = MoviePopular() - list.query() + await list.load_parameters() + await list.query() test_result = results['results'][-1]['title'] - tested = list.getListText()[(len(results['results'][-1]['title'])) * -1:] + tested = await list.getListText() + tested = tested[(len(results['results'][-1]['title'])) * -1:] self.assertEqual(tested, test_result) -''' + await list.close_session() if __name__ == '__main__': unittest.main() diff --git a/tmdb/tmdb.py b/tmdb/tmdb.py index 5819753..95e9044 100644 --- a/tmdb/tmdb.py +++ b/tmdb/tmdb.py @@ -57,6 +57,7 @@ class TmdbBot(Plugin): async def start(self) -> None: await super().start() self.db = Database(self.database) + self.api = None # async def send_movie_info(self, evt: MessageEvent, movie) -> None: # mxc_uri = await self.client.upload_media(data=movie.get_image_binary()) @@ -136,15 +137,20 @@ class TmdbBot(Plugin): await self.send_image(evt, movie.title, movie.get_image_binary()) async def init_movie(self): - movie = Movie() - await movie.load_parameters() - return movie + self.api = Movie() + await self.api.load_parameters() + return self.api async def init_tvshow(self): show = TvShow() await show.load_parameters() return show + async def init_moviepopular(self): + movie = MoviePopular() + await movie.load_parameters() + return movie + async def movie_id(self, evt: MessageEvent, message: str = "") -> None: movie = await self.init_movie() self.poster_size(evt, movie) @@ -160,12 +166,14 @@ class TmdbBot(Plugin): await self.movie_id(evt, message) async def movie_popular(self, evt: MessageEvent, message: str = "") -> None: - popular = MoviePopular() + popular = await self.init_moviepopular() language = self.db.get_language(evt.sender) if language: popular.set_language(language) length = 5 - await self.send_html_message(evt, popular.getListText(length), popular.getListHtml(length)) + text = await popular.getListText(length) + html = await popular.getListHtml(length) + await self.send_html_message(evt, text, html) @command.new("movie-search", help="Movie lookup by Title") @command.argument("message", pass_raw=True, required=True) @@ -225,15 +233,15 @@ class TmdbBot(Plugin): await self.tvshow_search(evt, message) async def movie_search(self, evt: MessageEvent, message: str = "") -> None: - movie = await self.init_movie() - self.poster_size(evt, movie) + await self.init_movie() + self.poster_size(evt, self.api) language = self.db.get_language(evt.sender) if language: - movie.set_language(language) + self.api.set_language(language) title, year = self.split_title_year(message) - await movie.search_title(title, year) - if movie.valid: - await self.send_movie_info(evt, movie) + await self.api.search_title(title, year) + if self.api.valid: + await self.send_movie_info(evt, self.api) else: content = TextMessageEventContent( msgtype=MessageType.NOTICE, format=Format.HTML, @@ -276,3 +284,5 @@ class TmdbBot(Plugin): await self.send_help(evt) else: await self.send_help(evt) + if self.api: + self.api.close_session() diff --git a/tmdb/tmdb_api.py b/tmdb/tmdb_api.py index 491fb8a..efde1bb 100644 --- a/tmdb/tmdb_api.py +++ b/tmdb/tmdb_api.py @@ -88,14 +88,14 @@ class MoviePopular(TmdbApi): self.list = [] self.length = 0 - def query(self) -> int: - result = self.request('/movie/popular') + async def query(self) -> int: + result = await self.request('/movie/popular') self.length = result['total_results'] self.list = result['results'] return self.length - def getListHtml(self, length: int = None) -> str: - self.query() + async def getListHtml(self, length: int = None) -> str: + await self.query() html = "" if length: loop = length @@ -105,8 +105,8 @@ class MoviePopular(TmdbApi): html += f"""

{escape(element['title'])}

""" return html - def getListText(self, length: int = None) -> str: - self.query() + async def getListText(self, length: int = None) -> str: + await self.query() text = "" if length: loop = length From 339998ab93e1cf4bea3629f4ffd7b15399959960 Mon Sep 17 00:00:00 2001 From: lomion Date: Thu, 23 Sep 2021 22:22:35 +0200 Subject: [PATCH 10/17] Fixed Flake --- test_tmdb.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/test_tmdb.py b/test_tmdb.py index 1f532ac..eab2605 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -2,25 +2,26 @@ import unittest from html import escape from tmdb.tmdb_api import Movie, TvShow, MoviePopular -from tmdb.tmdb import TmdbBot, MessageConstructor +from tmdb.tmdb import TmdbBot from tmdb.database import Database from sqlalchemy import create_engine -import time -import requests +import aiohttp -def apiRequests(command): + +async def apiRequests(command): api_key = '51d75c00dc1502dc894b7773ec3e7a15' base_url = "https://api.themoviedb.org/3/" url = base_url + command.lstrip('/') params = {'api_key': api_key} params.update({'language': 'en'}) - return requests.get(url, params=params).json() + async with aiohttp.ClientSession() as client: + async with client.get(url, params=params) as resp: + return await resp.json() class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): # TMDB API async def test_search_item(self): - start = time.time() movie = Movie() await movie.load_parameters() id = await movie.search_title('Breakfast Club') @@ -139,7 +140,7 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): await movie.close_session() async def test_movie_popular_length(self): - results = apiRequests('/movie/popular') + results = await apiRequests('/movie/popular') list = MoviePopular() await list.load_parameters() text = await list.query() @@ -147,7 +148,7 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): await list.close_session() async def test_movie_popular_id(self): - results = apiRequests('/movie/popular') + results = await apiRequests('/movie/popular') list = MoviePopular() await list.load_parameters() await list.query() @@ -155,7 +156,7 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): await list.close_session() async def test_movie_popular_html(self): - results = apiRequests('/movie/popular') + results = await apiRequests('/movie/popular') list = MoviePopular() await list.load_parameters() await list.query() @@ -166,7 +167,7 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): await list.close_session() async def test_movie_popular_text(self): - results = apiRequests('/movie/popular') + results = await apiRequests('/movie/popular') list = MoviePopular() await list.load_parameters() await list.query() @@ -176,5 +177,6 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): self.assertEqual(tested, test_result) await list.close_session() + if __name__ == '__main__': unittest.main() From f6ef56fe9357bcb272fd8de315fa922f9b7770fd Mon Sep 17 00:00:00 2001 From: lomion Date: Thu, 23 Sep 2021 22:32:07 +0200 Subject: [PATCH 11/17] New maubot version requires additional parameter --- test_tmdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_tmdb.py b/test_tmdb.py index eab2605..f6005da 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -92,7 +92,7 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): await movie.close_session() def test_split_year(self): - tmdb = TmdbBot("", "", "", "", "", "", "", "", "") + tmdb = TmdbBot("", "", "", "", "", "", "", "", "", "") title, year = tmdb.split_title_year('Dune') self.assertEqual('Dune', title) self.assertEqual(None, year) From 16336d61f3e16e9330dac23a7b7c7cd0bf220fda Mon Sep 17 00:00:00 2001 From: lomion Date: Mon, 8 Nov 2021 22:28:34 +0100 Subject: [PATCH 12/17] Fixed MoviesPopular --- tmdb/tmdb.py | 6 +++++- tmdb/tmdb_api.py | 6 ++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tmdb/tmdb.py b/tmdb/tmdb.py index 5819753..a85f6c6 100644 --- a/tmdb/tmdb.py +++ b/tmdb/tmdb.py @@ -161,11 +161,15 @@ class TmdbBot(Plugin): async def movie_popular(self, evt: MessageEvent, message: str = "") -> None: popular = MoviePopular() + await popular.load_parameters() language = self.db.get_language(evt.sender) if language: popular.set_language(language) length = 5 - await self.send_html_message(evt, popular.getListText(length), popular.getListHtml(length)) + await popular.query() + text = popular.getListText(length) + html = popular.getListHtml(length) + await self.send_html_message(evt, text, html) @command.new("movie-search", help="Movie lookup by Title") @command.argument("message", pass_raw=True, required=True) diff --git a/tmdb/tmdb_api.py b/tmdb/tmdb_api.py index 491fb8a..fe79364 100644 --- a/tmdb/tmdb_api.py +++ b/tmdb/tmdb_api.py @@ -88,14 +88,13 @@ class MoviePopular(TmdbApi): self.list = [] self.length = 0 - def query(self) -> int: - result = self.request('/movie/popular') + async def query(self) -> int: + result = await self.request('/movie/popular') self.length = result['total_results'] self.list = result['results'] return self.length def getListHtml(self, length: int = None) -> str: - self.query() html = "" if length: loop = length @@ -106,7 +105,6 @@ class MoviePopular(TmdbApi): return html def getListText(self, length: int = None) -> str: - self.query() text = "" if length: loop = length From 81ce86fc60dcd9db999adf8e178323c993caebf7 Mon Sep 17 00:00:00 2001 From: lomion Date: Mon, 8 Nov 2021 22:33:30 +0100 Subject: [PATCH 13/17] Clean up Removes search for id --- tmdb/tmdb.py | 46 +--------------------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/tmdb/tmdb.py b/tmdb/tmdb.py index a85f6c6..e3dfa41 100644 --- a/tmdb/tmdb.py +++ b/tmdb/tmdb.py @@ -58,22 +58,6 @@ class TmdbBot(Plugin): await super().start() self.db = Database(self.database) -# async def send_movie_info(self, evt: MessageEvent, movie) -> None: -# mxc_uri = await self.client.upload_media(data=movie.get_image_binary()) -# text_message = f'{movie.title}' -# if len(movie.overview) > 200: -# three_dotts = " [...]" -# else: -# three_dotts = "" -# cast = "Acting: " -# for actor in movie.cast[:3]: -# cast += f'{actor}, ' -# cast = cast[:-2] -# html_message = f"""

{escape(movie.title)}

-#

{escape(movie.overview)[:200]}{three_dotts}

-#

{cast}

-#

taken from www.themoviedb.org

""" - async def send_html_message(self, evt: MessageEvent, text_message: str, html_message: str) -> None: content = TextMessageEventContent( msgtype=MessageType.TEXT, format=Format.HTML, @@ -88,8 +72,7 @@ class TmdbBot(Plugin): await evt.respond(content) async def send_help(self, evt: MessageEvent) -> None: - html = """

Use !tmdb id movie {tmdb id} to get movie detail for tmdb-id.

-

Use !tmdb movie {title} [y:{release year}] to get movie detail based on the given title.

+ html = """

Use !tmdb movie {title} [y:{release year}] to get movie detail based on the given title.

Use !tmdb popular to get most popular movies.

Use !tmdb language {language} to set your prefered language.

Use !tmdb poster_size [{size}] to set your prefered poster size. With empty {size} all available sizes are listed.

@@ -145,20 +128,6 @@ class TmdbBot(Plugin): await show.load_parameters() return show - async def movie_id(self, evt: MessageEvent, message: str = "") -> None: - movie = await self.init_movie() - self.poster_size(evt, movie) - language = self.db.get_language(evt.sender) - if language: - movie.set_language(language) - await movie.query_details(message) - await self.send_movie_info(evt, movie) - - @command.new("movie-id", help="Movie lookup by id") - @command.argument("message", pass_raw=True, required=True) - async def command_movie_id(self, evt: MessageEvent, message: str = "") -> None: - await self.movie_id(evt, message) - async def movie_popular(self, evt: MessageEvent, message: str = "") -> None: popular = MoviePopular() await popular.load_parameters() @@ -263,19 +232,6 @@ class TmdbBot(Plugin): await self.set_poster_size(evt, parameters) elif command.lower() == 'tvshow': await self.tvshow_search(evt, parameters) - elif command.lower() == 'id': - m = re.search(r'^(movie|tvshow) (\d*)', parameters) - if m: - type = m.group(1) - id = m.group(2) - if type.lower() == 'movie': - await self.movie_id(evt, id) - elif type.lower() == 'tvshow': - await self.send_notice(evt, 'Not yet implemented. Search TV shows by title for now (!tmdb tvshow {title})') - else: - await self.send_notice(evt, 'Syntax wrong: !tmdb id {movie|tvshow} {tmdb id}') - else: - await self.send_notice(evt, 'Syntax wrong: !tmdb id {movie|tvshow} {tmdb id}') else: await self.send_help(evt) else: From 2c78919b7ff0af0ac2023c82e4fe31950fb2069f Mon Sep 17 00:00:00 2001 From: lomion Date: Mon, 8 Nov 2021 22:48:18 +0100 Subject: [PATCH 14/17] Fixed Unittests --- test_tmdb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test_tmdb.py b/test_tmdb.py index f6005da..e2ce2fe 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -136,7 +136,7 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): movie = Movie() await movie.load_parameters() await movie.search_title('Dune') - self.assertEqual(movie.poster_url, "http://image.tmdb.org/t/p/w92/lr3cYNDlJcpT1EWzFH42aSIvkab.jpg") + self.assertEqual(movie.poster_url, "http://image.tmdb.org/t/p/w92/d5NXSklXo0qyIYkgV94XAgMIckC.jpg") await movie.close_session() async def test_movie_popular_length(self): @@ -161,7 +161,7 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): await list.load_parameters() await list.query() test_result = escape(results['results'][-1]['title']) - tested = await list.getListHtml() + tested = list.getListHtml() tested = tested[(len(results['results'][-1]['title']) + 8) * -1:] self.assertEqual(tested, f"""{test_result}

""") await list.close_session() @@ -172,7 +172,7 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): await list.load_parameters() await list.query() test_result = results['results'][-1]['title'] - tested = await list.getListText() + tested = list.getListText() tested = tested[(len(results['results'][-1]['title'])) * -1:] self.assertEqual(tested, test_result) await list.close_session() From e62000098da48a01b6c6a1158494f61e3a98b0d8 Mon Sep 17 00:00:00 2001 From: Lomion Date: Thu, 11 Nov 2021 13:54:53 +0100 Subject: [PATCH 15/17] Fixed test for name without y: --- test_tmdb.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test_tmdb.py b/test_tmdb.py index 9e6276a..d7eefda 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -112,9 +112,10 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): self.assertEqual(size, None) await movie.close_session() - def test_year_no_y(self): + async def test_year_no_y(self): movie = Movie() - id = movie.search_title('infinite 2021') + await movie.load_parameters() + id = await movie.search_title('infinite 2021') self.assertEqual(id, None) self.assertEqual(movie.valid, False) From 88a65d3272fc9fa4954277d13fcfb372564e3a2f Mon Sep 17 00:00:00 2001 From: Lomion Date: Thu, 11 Nov 2021 13:57:21 +0100 Subject: [PATCH 16/17] Prepared Release 1.2.0 --- README.md | 2 -- maubot.yaml | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 06dc54f..3a00f9a 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ A [maubot](https://github.com/maubot/maubot) to get information about movies fro ## Usage Use `!tmdb help` to get help about the bot usage. -Use `!tmdb id movie {tmdb id}` to get movie detail for tmdb-id. - Use `!tmdb movie {title} [y:{release year}]` to get movie detail based on the given title. Use `!tmdb popular` to get most popular movies. diff --git a/maubot.yaml b/maubot.yaml index 9c32ad3..3fa536f 100644 --- a/maubot.yaml +++ b/maubot.yaml @@ -1,6 +1,6 @@ maubot: 0.1.0 id: lomion.tmdb -version: 1.0.2 +version: 1.2.0 license: AGPL 3.0 modules: - tmdb From a53cb1a56ef2be83722c925d4acdc683d88c71b4 Mon Sep 17 00:00:00 2001 From: lomion Date: Thu, 11 Nov 2021 20:13:28 +0100 Subject: [PATCH 17/17] Removed HTML unit test --- test_tmdb.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/test_tmdb.py b/test_tmdb.py index d7eefda..2f58489 100644 --- a/test_tmdb.py +++ b/test_tmdb.py @@ -164,17 +164,6 @@ class TestTmdbMethods(unittest.IsolatedAsyncioTestCase): self.assertEqual(list.list[2]['id'], results['results'][2]['id']) await list.close_session() - async def test_movie_popular_html(self): - results = await apiRequests('/movie/popular') - list = MoviePopular() - await list.load_parameters() - await list.query() - test_result = escape(results['results'][-1]['title']) - tested = list.getListHtml() - tested = tested[(len(results['results'][-1]['title']) + 8) * -1:] - self.assertEqual(tested, f"""{test_result}

""") - await list.close_session() - async def test_movie_popular_text(self): results = await apiRequests('/movie/popular') list = MoviePopular()