Unlock a world of anime information from a single scene screenshot – Including episode, timestamps, and much more!
import os.path
import requests
import json

def json_to_tabular(self, iad=False):
    # Accessing information in the JSON data
    result = self.a['result']
    formatted_data = ""
    for entry in result:
        anilist = entry['anilist']
        filename = entry['filename']
        episode = entry['episode']
        from_time = entry['from']
        to_time = entry['to']
        similarity = entry['similarity'] * 100
        video_url = entry['video']
        image_url = entry['image']

        # Format the data with labels and insert into the QTextEdit widget

        if iad is False:
            formatted_data += (
                f"Filename: {filename}\n"
                f"Episode: {episode}\n"
                f"From: {from_time}\n"
                f"To: {to_time}\n"
                f"Similarity: {similarity:.2f}%\n\n"
            )
        else:
            formatted_data += (
                f"Filename: {filename}\n"
                f"Episode: {episode}\n"
                f"From: {from_time}\n"
                f"To: {to_time}\n"
                f"Similarity: {similarity:.2f}%\n\n"
                f"From: {from_time}\n"
                f"To: {to_time}\n"
                f"Anilist: {anilist}\n"
                f"Video URL: {video_url}\n"
                f"Image URL: {image_url}\n"

            )

    self.textbox.setPlainText(formatted_data)


def write_to_json(self):
    # Open a file dialog to select a file to write to
    options = QFileDialog.Options()
    file_path, _ = QFileDialog.getSaveFileName(self, "Save JSON File", "", "JSON Files (*.json);;All Files (*)",
                                               options=options)

    if file_path:
        try:
            # Open the selected file in write mode and write the JSON data
            with open(file_path, "w") as file:
                json.dump(self.a, file)

            # Inform the user that the file has been saved
            QMessageBox.information(self, "File Saved", "The file has been saved successfully.")
        except Exception as e:
            # Handle any exceptions that may occur
            QMessageBox.critical(self, "Error", f"An error occurred: {str(e)}")


src/json_operations.py
rohankishore/AnimeSnap
import sys
import os
import json_operations
import search
import qdarktheme
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *


class App(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("AnimeSnap")
        self.setGeometry(100, 100, 450, 150)

        self.img_path = ""
        self.img_url = ""
        self.anilist_id = ""
        self.ctheme = "dark"

        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        layout = QVBoxLayout()
        central_widget.setLayout(layout)

        self.buttons_frame = QWidget()
        layout.addWidget(self.buttons_frame)

        # Create a horizontal layout
        top_layout = QHBoxLayout()
        button_layout = QHBoxLayout()
        checkbox_layout = QHBoxLayout()

        theme_icon = QIcon("icons/dark.png")
        self.themes_button = QPushButton(self)
        self.themes_button.setIconSize(QSize(23, 23))
        self.themes_button.clicked.connect(self.onClickThemeIcon)
        self.themes_button.setIcon(theme_icon)
        self.themes_button.setText("")
        self.themes_button.setFixedSize(23, 23)
        top_layout.addStretch()
        top_layout.addWidget(self.themes_button)

        layout.addLayout(top_layout)

        layout.addWidget(QLabel(""))

        self.img_url_entry = QLineEdit(self)
        self.img_url_entry.setPlaceholderText("Enter image URL or Upload a image")

        self.file_path_label = QLabel("")

        button_layout.addWidget(self.img_url_entry)


        open_image_icon = QIcon("icons/folder.png")
        self.open_image_button = QPushButton(self)
        self.open_image_button.clicked.connect(self.open_image)
        self.open_image_button.setIcon(open_image_icon)
        self.open_image_button.setIconSize(QSize(23, 23))
        self.open_image_button.setFixedSize(28, 28)
        button_layout.addWidget(self.open_image_button)

        layout.addLayout(button_layout)# Add the button layout to the main layout
        layout.addWidget(self.file_path_label)

        layout.addWidget(QLabel(""))

        layout.addLayout(checkbox_layout)  # Add the checkbox layout to the main layout

        self.checkbox_rbb = QCheckBox("Remove Black Borders")
        checkbox_layout.addWidget(self.checkbox_rbb)

        self.checkbox_iad = QCheckBox("Include All Details")
        checkbox_layout.addWidget(self.checkbox_iad)

        layout.addWidget(QLabel(""))

        layout.addWidget(QLabel("Anilist Anime ID [OPTIONAL] [https://anilist.co/]"))

        self.anilist_entry = QLineEdit(self)
        self.anilist_entry.setPlaceholderText("Use this if you know what anime it is and you just need the scene details")
        layout.addWidget(self.anilist_entry)


        search_button = QPushButton("Search")
        search_button.clicked.connect(self.onClickSearch)
        layout.addWidget(search_button)

    def open_image(self):
        #options = QFileDialog.Options()
        file_path, _ = QFileDialog.getOpenFileName(self, "Open Image to Search", "", "Image Files (*.jpg *.png *.bmp);;All Files (*)")

        if file_path:
            self.img_path = file_path
            self.file_path_label.setText(file_path)

    def returnToMenu(self):
        self.stacked_widget.setCurrentWidget(self.main_menu_widget)
        self.img_path = ""
        self.main_menu_widget.file_path_label.setPlainText("")

    def onClickThemeIcon(self):
        if self.ctheme == "dark":
            self.ctheme = "light"
            qdarktheme.setup_theme("light")
        else:
            self.ctheme = "dark"
            qdarktheme.setup_theme("dark")
        self.onThemeIconVisibilityChanged()

    def onThemeIconVisibilityChanged(self):
        if self.ctheme == "dark":
            self.themes_button.setIcon(QIcon('icons/dark.png'))
        else:
            self.themes_button.setIcon(QIcon('icons/light.png'))

    def onClickSearch(self):
        # Clear the layout
        while self.layout().count():
            item = self.layout().takeAt(0)
            widget = item.widget()
            if widget is not None:
                widget.deleteLater()

        self.img_url = self.img_url_entry.text()
        anilist_id = self.anilist_entry.text()
        anilist_status = ""
        rbb_status = ""
        iad_status = ""

        if self.checkbox_iad.isChecked():
            iad_status = True
        else:
            iad_status = False

        if self.checkbox_rbb.isChecked():
            rbb_status = True
        else:
            rbb_status = False

        if anilist_id == "":
            anilist_status = None
        else:
            anilist_status = anilist_id

        if self.img_url == "":
            search.search_img(self, anilist_info=anilist_status, rbb=rbb_status)
        else:
            search.search_url(self)

        if iad_status is True:
            json_operations.json_to_tabular(self, iad=True)
        else:
            json_operations.json_to_tabular(self, iad=False)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    qdarktheme.setup_theme("dark")
    window = App()
    window.show()
    sys.exit(app.exec())

src/main.py
rohankishore/AnimeSnap
import os.path
import json_operations
import requests
import urllib
import json
from PyQt6.QtWidgets import QVBoxLayout, QTextEdit, QPushButton, QWidget


def search_img(self, anilist_info = None, rbb=False):
    self.setGeometry(100, 100, 750, 800)
    self.a = ""

    if anilist_info is None:
        self.a  = requests.post("https://api.trace.moe/search",
                                 files={"image": open(f"{self.img_path}", "rb")}
                                 ).json()
    else:
        if rbb is False:
            url = f"https://api.trace.moe/search?anilistID={anilist_info}&url=" + "{}"
            self.a = requests.get(url
                                  .format(urllib.parse.quote_plus(f"{self.img_path}"))).json()
        else:
            url = f"https://api.trace.moe/search?anilistID={anilist_info}&url="+"{}"
            self.a = requests.get(url
                                  .format(urllib.parse.quote_plus(f"{self.img_path}"))).json()


    self.textbox = QTextEdit()
    self.textbox.setPlainText(str(self.a)+ "\n" + "\n")
    self.textbox.setReadOnly(True)

    layout = QVBoxLayout()
    layout.addWidget(self.textbox)

    json_button = QPushButton("Write to JSON")
    json_button.clicked.connect(lambda: json_operations.write_to_json(self))
    layout.addWidget(json_button)

    another_image_button = QPushButton("Search Another Image")
    another_image_button.clicked.connect(self.returnToMenu)
    layout.addWidget(another_image_button)

    central_widget = QWidget()
    central_widget.setLayout(layout)
    self.setCentralWidget(central_widget)

def search_url(self, anilist_info = None, rbb = False):
    self.setGeometry(100, 100, 750, 800)
    self.a = ""
    if anilist_info is None:
        self.a = requests.post("https://api.trace.moe/search",
                               files={"image": open(f"{self.img_url}", "rb")}
                               ).json()
    else:
        if rbb is False:
            url = f"https://api.trace.moe/search?anilistID={anilist_info}&url="+"{}"
            self.a = requests.get(url
                                  .format(urllib.parse.quote_plus(f"{self.img_url}"))).json()
        else:
            url = "https://api.trace.moe/search?anilistID"+str(stranilist_info)+"&url="+"{}"
            self.a = requests.get(url
                                  .format(urllib.parse.quote_plus(f"{self.img_url}"))).json()

    self.textbox = QTextEdit()
    self.textbox.setPlainText(str(self.a)+ "\n" + "\n")
    self.textbox.setReadOnly(True)

    layout = QVBoxLayout()
    layout.addWidget(self.textbox)



    central_widget = QWidget()
    central_widget.setLayout(layout)
    self.setCentralWidget(central_widget)


src/search.py
rohankishore/AnimeSnap