├── run.sh
├── .env
├── img.png
├── .gitignore
├── CONTRIBUTING.md
├── requirements.txt
├── LICENSE
├── CODE_OF_CONDUCT.md
├── app.py
└── README.md
/run.sh:
--------------------------------------------------------------------------------
1 | nohup streamlit run app.py --server.port 5001 &
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | FLASK_API_URL=https://api.cinesimile.niweera.com/
2 |
--------------------------------------------------------------------------------
/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Niweera/cinesimile/HEAD/img.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.idea
6 | /.vscode
7 | /.pnp
8 | .pnp.js
9 | /venv
10 |
11 | # testing
12 | /coverage
13 | /cypress/videos
14 | /cypress/screenshots
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | .env.local
22 | .env.development.local
23 | .env.test.local
24 | .env.production.local
25 |
26 | npm-debug.log*
27 | yarn-debug.log*
28 | yarn-error.log*
29 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guidelines
2 |
3 | Welcome to CineSimile! 📽️
4 | CineSimile is an open source platform to find movie recommendations similar to a given movie. If you want to contribute to this project you can follow the following steps:
5 |
6 | 1. Fork and Clone the repository
7 | 2. Select an issue and work on it.
8 | 3. Create a Pull Request,
9 |
10 | # Additional resources
11 |
12 | - [How to Contribute to Open Source](http://opensource.guide/how-to-contribute/)
13 | - [FIRST TIMERS ONLY](https://www.firsttimersonly.com/)
14 | - [AWESOME FOR BEGINNERS](https://github.com/mungell/awesome-for-beginners)
15 | - [Useful Git Commands](https://github.com/joshnh/Git-Commands/blob/master/README.md)
16 | - [GitHub Training Kit](https://training.github.com/)
17 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | altair==5.2.0
2 | attrs==23.1.0
3 | blinker==1.7.0
4 | cachetools==5.3.2
5 | certifi==2023.11.17
6 | charset-normalizer==3.3.2
7 | click==8.1.7
8 | gitdb==4.0.11
9 | GitPython==3.1.40
10 | idna==3.6
11 | importlib-metadata==6.11.0
12 | Jinja2==3.1.2
13 | jsonschema==4.20.0
14 | jsonschema-specifications==2023.11.2
15 | markdown-it-py==3.0.0
16 | MarkupSafe==2.1.3
17 | mdurl==0.1.2
18 | numpy==1.26.2
19 | packaging==23.2
20 | pandas==2.1.4
21 | Pillow==10.1.0
22 | protobuf==4.25.1
23 | pyarrow==14.0.1
24 | pydeck==0.8.1b0
25 | Pygments==2.17.2
26 | python-dateutil==2.8.2
27 | python-dotenv==1.0.0
28 | pytz==2023.3.post1
29 | referencing==0.32.0
30 | requests==2.31.0
31 | rich==13.7.0
32 | rpds-py==0.13.2
33 | six==1.16.0
34 | smmap==5.0.1
35 | streamlit==1.29.0
36 | streamlit-searchbox==0.1.6
37 | tenacity==8.2.3
38 | toml==0.10.2
39 | toolz==0.12.0
40 | tornado==6.4
41 | typing_extensions==4.9.0
42 | tzdata==2023.3
43 | tzlocal==5.2
44 | urllib3==2.1.0
45 | validators==0.22.0
46 | watchdog==3.0.0
47 | zipp==3.17.0
48 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Nipuna Weerasekara
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at w.nipuna@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | from dotenv import load_dotenv
4 | import os
5 | import requests
6 | import streamlit as st
7 | from streamlit_searchbox import st_searchbox
8 |
9 | st.set_page_config(page_title="CineSimile", page_icon="🎬")
10 |
11 | # Load environment variables
12 | load_dotenv()
13 |
14 | # API Base URL
15 | API_BASE_URL = os.getenv("FLASK_API_URL") # Replace with your Flask API URL
16 |
17 |
18 | # Function to check API accessibility
19 | def is_api_accessible():
20 | try:
21 | response = requests.get(API_BASE_URL)
22 | return response.status_code == 200
23 | except:
24 | return False
25 |
26 |
27 | # Check if the API is accessible
28 | api_accessible = is_api_accessible()
29 |
30 |
31 | # Function to get movie suggestions
32 | def get_movie_suggestions(query):
33 | response = requests.get(f"{API_BASE_URL}/suggest?query={query}")
34 | if response.status_code == 200:
35 | suggestions = response.json()
36 | return [f"{s['Name']} ({s['Date']})" for s in suggestions]
37 | return []
38 |
39 |
40 | # Function to get movie recommendations
41 | def get_movie_recommendations(movie_name, movie_year, engine):
42 | response = requests.get(
43 | f"{API_BASE_URL}/recommend/{engine}?name={movie_name}&year={movie_year}"
44 | )
45 | if response.status_code == 200:
46 | return response.json()
47 | return []
48 |
49 |
50 | # Define a wrapper function for get_movie_suggestions to be used in st_searchbox
51 | def search_function(query):
52 | if query:
53 | return get_movie_suggestions(query)
54 | return []
55 |
56 |
57 | # Streamlit UI
58 |
59 | st.title("🎬 CineSimile")
60 | st.subheader("AI is here to take over the world.")
61 | st.subheader("In the meantime, here's a good movie to watch!")
62 |
63 | # Disable UI if API is not accessible
64 | if not api_accessible:
65 | st.error("CineSimile-API is currently inaccessible. Please try again later.")
66 | st.stop()
67 |
68 | # Movie name input with autocomplete suggestions
69 | st.write("Enter the name of a movie")
70 |
71 | selected_movie = st_searchbox(
72 | label="",
73 | search_function=search_function,
74 | placeholder="Start typing...",
75 | help_text="Select a movie from the list",
76 | clear_on_submit=False,
77 | )
78 |
79 | st.write("Find similar movies using:")
80 | # Buttons for each recommendation engine
81 | engines = ["cosine", "euclidean", "pearson", "jaccard", "manhattan"]
82 | # Create a row of columns for the buttons
83 | selected_engine = None
84 | cols = st.columns(len(engines))
85 | for idx, engine in enumerate(engines):
86 | with cols[idx]:
87 | if st.button(engine.capitalize(), use_container_width=True):
88 | selected_engine = engine
89 |
90 | # Display recommendations
91 | if selected_engine and selected_movie:
92 | year_match = re.search(r"\((\d{4})\)", selected_movie)
93 |
94 | if not year_match:
95 | st.error("Please select a movie with a valid year")
96 |
97 | movie_year = int(year_match.group(1))
98 | movie_name = selected_movie.replace(year_match.group(0), "").strip()
99 |
100 | similar_movies = get_movie_recommendations(movie_name, movie_year, selected_engine)
101 |
102 | # Display the movies and their posters horizontally
103 | cols = st.columns(len(similar_movies)) # Create columns
104 | for idx, movie in enumerate(similar_movies):
105 | with cols[idx]:
106 | st.image(
107 | movie.get("poster", {}).get(
108 | "poster",
109 | "https://s.studiobinder.com/wp-content/uploads/2017/12/Movie-Poster-Template-Dark-with-Image.jpg",
110 | )
111 | )
112 | st.markdown(f"**{movie['name']} ({movie['year']})**")
113 | elif selected_engine and not selected_movie:
114 | st.error("Please enter and select a movie name from the suggestions")
115 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](CONTRIBUTING.md)
2 | [](https://github.com/ellerbrock/open-source-badges/)
3 | [](https://opensource.org/licenses/mit-license.php)
4 | [](http://makeapullrequest.com)
5 | [](https://cinesimile.niweera.com/)
6 | [](https://GitHub.com/Niweera/cinesimile/network/)
7 | [](https://GitHub.com/Niweera/cinesimile/stargazers/)
8 | [](https://GitHub.com/Niweera/cinesimile/watchers/)
9 | [](https://GitHub.com/Niweera/cinesimile/graphs/contributors/)
10 | [](https://GitHub.com/Niweera/cinesimile/issues/)
11 | [](https://GitHub.com/Niweera/cinesimile/issues?q=is%3Aissue+is%3Aclosed)
12 | [](https://GitHub.com/Niweera/cinesimile/pulls/)
13 | [](https://GitHub.com/Niweera/cinesimile/pulls/)
14 |
15 | [](https://cinesimile.niweera.com/)
16 | [](https://cinesimile.niweera.com/)
17 | [](https://cinesimile.niweera.com/)
18 | [](https://cinesimile.niweera.com/)
19 | [](https://cinesimile.niweera.com/)
20 |
21 |
AI is here to take over the world. In the meantime, here's a good movie to watch!
23 |