Пример #1
0
    def __init__(self):
        super(SimpleExample1, self).__init__('Simple example 1')

        #Definition of the forms fields
        self._firstname = ControlText('First name', 'Default value')
        self._middlename = ControlText('Middle name')
        self._lastname = ControlText('Lastname name')
        self._fullname = ControlText('Full name')
        self._button = ControlButton('Press this button')
 def __init__(self):
     super(SAHostPortInput, self).__init__("SA Websocket")
     self._host = ControlText("Host IP")
     self._port = ControlText("Host Port")
     self._host.value = "localhost"
     self._port.value = "58341"
     self._button = ControlButton("Submit")
     self.formset = ["_host", "_port", "_button"]
     self._button.value = self.__button_action
 def __init__(self):
     super(OBSHostPortInput, self).__init__("OBS Websocket")
     self._host = ControlText("Host IP")
     self._port = ControlText("Host Port")
     self._host.value = "localhost"
     self._port.value = "4444"
     self._label = ControlLabel(
         "When I stop recording I want the program to")
     self._sub = ControlButton("Submit")
     self._stop = ControlButton("Stop Updates")
     self.formset = ["_host", "_port", "_label", ("_sub", "_stop")]
     self._sub.value = self.__sub_action
     self._stop.value = self.__stop_action
Пример #4
0
    def __init__(self, parent=None):
        super(CsvParserDialog, self).__init__('CSV Choose the columns',
                                              parent_win=parent)
        self._filename = None

        # Definition of the forms fields
        self._filename = ControlFile('CSV File')
        self._separator = ControlText('Separator', default=';')
        self._startingrow = ControlNumber('Starting row', default=0)
        self._frameCol = ControlNumber('Frame column',
                                       default=0,
                                       minumum=0,
                                       maximum=100)
        self._xCol = ControlNumber('X column',
                                   default=1,
                                   minumum=0,
                                   maximum=100)
        self._yCol = ControlNumber('Y column',
                                   default=2,
                                   minumum=0,
                                   maximum=100)
        self._zCol = ControlNumber('Z column',
                                   default=3,
                                   minumum=0,
                                   maximum=100)
        self._filePreview = ControlList('Preview')
        self._loadButton = ControlButton('Load')

        self._formset = [('_filename', '_startingrow'),
                         ('_separator', '_frameCol', '_xCol', '_yCol', '_zCol',
                          '_loadButton'), '_filePreview']
        self._separator.changed_event = self.__refreshPreview
        self._filename.changed_event = self.__refreshPreview
        self._startingrow.changed_event = self.__refreshPreview
    def __init__(self, url=""):
        super(SMurlInput, self).__init__("Streameta")
        self._url = ControlText("URL")
        self._url.value = url.value
        self._url.form.lineEdit.setPlaceholderText(
            "http://ns.streameta.com/api/?token=<token>")

        self._button = ControlButton('Submit')
        self._button.value = self.__button_action
Пример #6
0
    def __init__(self, mappings={}):
        super(SCSetup, self).__init__("Stream Control")
        self._mappings = mappings
        self._file = ControlFile("File")

        self._label = ControlLabel(
            "Uploader Inputs to streamcontrol.json mappings\n")
        self._p1 = ControlText("P1 Name")
        self._p2 = ControlText("P2 Name")
        self._p1_sponsor = ControlText("P1 Sponsor")
        self._p2_sponsor = ControlText("P2 Sponsor")
        self._p1_char = ControlText("P1 Character")
        self._p2_char = ControlText("P2 Character")
        self._mtype = ControlText("Match Type")
        self._mprefix = ControlText("Match Prefix")

        self._button = ControlButton("Submit")
        self.formset = [
            "_file",
            "_label",
            "_p1",
            "_p2",
            "_p1_sponsor",
            "_p2_sponsor",
            "_p1_char",
            "_p2_char",
            "_mtype",
            "_mprefix",
            (" ", "_button", " "),
        ]

        self._p1.value = self._mappings.get("p1_name", "")
        self._p2.value = self._mappings.get("p2_name", "")
        self._p1_sponsor.value = self._mappings.get("p1_sponsor", "")
        self._p2_sponsor.value = self._mappings.get("p2_sponsor", "")
        self._p1_char.value = self._mappings.get("p1_char", "")
        self._p2_char.value = self._mappings.get("p2_char", "")
        self._mtype.value = self._mappings.get("mtype", "")
        self._mprefix.value = self._mappings.get("mprefix", "")

        self._file.value = self._mappings.get("file", "")

        self._file.form.lineEdit.setPlaceholderText(
            "Find your streamcontrol.json")

        self._button.value = self.__button_action
    def __init__(self):
        try:  # check if the user can update the app
            latest_version = requests.get(
                'https://pypi.org/pypi/MeleeUploader/json').json(
                )['info']['version']
            if sv(latest_version) > sv(
                    consts.__version__):  # prevents messages when developing
                if "linux" in sys.platform:
                    self.info(
                        f"Current Version: {consts.__version__}\nVersion {latest_version} is available.\nUse sudo pip3 install -U meleeuploader=={latest_version} in terminal to update to the newest verison",
                        title="MeleeUploader")
                else:
                    resp = self.question(
                        f"Current Version: {consts.__version__}\nVersion {latest_version} is available. Would you like to update?",
                        title="MeleeUploader")
                    if resp == "yes":
                        ret = subprocess.call(
                            ('pip3', 'install', '-U',
                             f'meleeuploader=={latest_version}'))
                        if ret:
                            self.info(
                                f'The app failed to update\nType "pip3 install -U meleeuploader=={latest_version}" into CMD/Terminal to update',
                                title="MeleeUploader")
                        else:
                            self.info(
                                "You can now restart the app to use the new version",
                                title="MeleeUploader")
        except Exception as e:
            print(e)

        if consts.melee:
            super(MeleeUploader, self).__init__("Melee YouTube Uploader")
        else:
            super(MeleeUploader, self).__init__("Smash YouTube Uploader")

        # Redirct print output
        sys.stdout = workers.WriteWorker(textWritten=self.write_print)

        # Redirect error output to window, console, and file
        sys.stderr = workers.WriteWorker(textWritten=self.write_err)

        # Websocket
        self._sa = None
        self._obs = None

        # History
        self.__history = []

        # Queue
        self._queue = Queue()
        self._queueref = []

        # Event Values
        self._privacy = ControlCombo("Video Privacy")
        self._titleformat = ControlCombo("Title Format")
        self._ename = ControlText("Event Name")
        self._ename_min = ControlText()
        self._pID = ControlText("Playlist ID")
        self._bracket = ControlText("Bracket Link")
        self._tags = ControlText("Tags")
        self._description = ControlTextArea("Description")

        # Match Values
        self._file = ControlFile("File")
        self._p1 = ControlText()
        self._p2 = ControlText()
        self._p1sponsor = ControlText("P1")
        self._p2sponsor = ControlText("P2")
        self._p1char = ControlCheckBoxList("P1 Characters")
        self._p2char = ControlCheckBoxList("P2 Characters")
        self._mtype = ControlCombo()
        self._mprefix = ControlText()
        self._msuffix = ControlText()

        # Output Box
        self._output = ControlTextArea()
        self._output.readonly = True
        self._qview = ControlList("Queue", select_entire_row=True)
        self._qview.cell_double_clicked_event = self.__show_o_view
        self._qview.readonly = True
        self._qview.horizontal_headers = ["Player 1", "Player 2", "Round"]

        # Button
        self._button = ControlButton('Submit')
        self._button.value = self.__button_action

        # Title Formats
        for f in consts.titleformat:
            self._titleformat += f

        # Form Layout
        self.formset = [{
            "-Match": [
                "_file", (' ', "_mprefix", "_mtype", "_msuffix", ' '),
                (' ', "_p1sponsor", "_p1", ' '), (' ', "_p1char", ' '),
                (' ', "_p2sponsor", "_p2", ' '), (' ', "_p2char", ' ')
            ],
            "-Status-": ["_output", "=", "_qview"],
            "Event-": [
                "_privacy", "_titleformat", ("_ename", "_ename_min"), "_pID",
                "_bracket", "_tags", "_description"
            ]
        }, (' ', '_button', ' ')]

        # Main Menu Layout
        self.mainmenu = [{
            'Settings': [{
                'YouTube Log Out': self.__reset_cred
            }, {
                'Toggle OBS Hook': self.__show_obs_form
            }, {
                'Toggle SA Hook': self.__show_sa_form
            }, {
                'Toggle SC Hook': self.__show_sc_form
            }, {
                'Toggle Streameta Hook': self.__show_sm_form
            }, {
                'About': self.__about_info
            }],
            'Save/Clear': [{
                'Save Form': self.__save_form
            }, {
                'Clear Match Values': self.__reset_match
            }, {
                'Clear Event Values': self.__reset_event
            }, {
                'Clear All': self.__reset_forms
            }],
            'Queue': [{
                'Toggle Uploads': utils.toggle_worker
            }, {
                'Save Queue': self.__save_queue
            }, {
                'Load Queue': self.__load_queue
            }],
            'History': [{
                'Show History': self.__show_h_view
            }],
            'Characters': [{
                'Melee': self.__melee_chars
            }, {
                'Ultimate': self.__ultimate_chars
            }, {
                'Custom': self.__custom_chars
            }]
        }]

        # Add ControlCombo values
        for t in consts.match_types:
            self._mtype += t
        for t in ("public", "unlisted", "private"):
            self._privacy += t

        # Set placeholder text
        self._ename_min.form.lineEdit.setPlaceholderText(
            "Shortened Event Name")
        self._p1sponsor.form.lineEdit.setPlaceholderText("Sponsor Tag")
        self._p2sponsor.form.lineEdit.setPlaceholderText("Sponsor Tag")
        self._p1.form.lineEdit.setPlaceholderText("P1 Tag")
        self._p2.form.lineEdit.setPlaceholderText("P2 Tag")
        self._mprefix.form.lineEdit.setPlaceholderText("Round Prefix")
        self._msuffix.form.lineEdit.setPlaceholderText("Round Suffix")
        self._bracket.form.lineEdit.setPlaceholderText("Include https://")
        self._tags.form.lineEdit.setPlaceholderText("Separate with commas")
        self._pID.form.lineEdit.setPlaceholderText("Accepts full YT link")

        # For pulling characters
        self.__p1chars = []
        self.__p2chars = []

        # Set character list
        if consts.melee:
            self.__melee_chars()
        else:
            self.__ultimate_chars()

        # Stream Control
        self._sc = None
        self._scf = ControlText()
        self._scf.value = ""

        # Streameta
        self._sm = None
        self._smf = ControlText()
        self._smf.value = ""

        # Define the existing form fields
        self._form_fields = (self._ename, self._pID, self._mtype, self._p1,
                             self._p2, self._p1char, self._p2char,
                             self._bracket, self._file, self._tags,
                             self._msuffix, self._mprefix, self._p1sponsor,
                             self._p2sponsor, self._privacy, self._description,
                             self._ename_min, self._titleformat, self._scf,
                             self._smf)

        # Get latest values from form_values.txt
        self.__load_form()
Пример #8
0
    def __init__(self):
        try:  # check if the user can update the app
            latest_version = (requests.get(
                "https://pypi.org/pypi/MeleeUploader/json").json().get(
                    "info", {}).get("version"))
            if sv(latest_version) > sv(
                    consts.__version__):  # prevents messages when developing
                if "linux" in sys.platform:
                    self.info(
                        f"Current Version: {consts.__version__}\nVersion {latest_version} is available.\nUse sudo pip3 install -U meleeuploader=={latest_version} in terminal to update to the newest verison",
                        title="MeleeUploader",
                    )
                else:
                    resp = self.question(
                        f"Current Version: {consts.__version__}\nVersion {latest_version} is available. Would you like to update?",
                        title="MeleeUploader",
                    )
                    if resp == "yes":
                        ret = subprocess.call((
                            "pip3",
                            "install",
                            "-U",
                            f"meleeuploader=={latest_version}",
                        ))
                        if ret:
                            self.info(
                                f'The app failed to update\nType "pip3 install -U meleeuploader=={latest_version}" into CMD/Terminal to update',
                                title="MeleeUploader",
                            )
                        else:
                            self.info(
                                "You can now restart the app to use the new version",
                                title="MeleeUploader",
                            )
        except Exception as e:
            print(e)

        super(MeleeUploader,
              self).__init__(f"Melee YouTube Uploader - {consts.__version__}")

        # Redirct print output
        sys.stdout = workers.WriteWorker(textWritten=self.write_print)

        # Websocket
        self._sa = None
        self._obs = None

        # History
        self.__history = []

        # Queue
        self._queue = Queue()
        self._queueref = (
            [])  # out of order access to all the items in _queue with mutation
        consts.start_queue = True if "-q" in sys.argv else False

        # Event Values
        self._privacy = ControlCombo("Video Privacy")
        self._title_format = ControlCombo("Title Format")
        self._ename = ControlText("Event Name")
        self._ename_min = ControlText()
        self._pID = ControlText("Playlist ID")
        self._bracket = ControlText("Bracket Link")
        self._tags = ControlText("Tags")
        self._description = ControlTextArea("Description")
        self._timestamp_start = None
        self._timestamps = []

        # Match Values
        self._file = ControlFile("File")
        self._p1 = ControlText()
        self._p2 = ControlText()
        self._p1_sponsor = ControlText("P1")
        self._p2_sponsor = ControlText("P2")
        self._p1char = ControlCheckBoxList("P1 Characters")
        self._p2char = ControlCheckBoxList("P2 Characters")
        self._mtype = ControlCombo()
        self._mprefix = ControlText()
        self._msuffix = ControlText()

        # Output Box
        self._output = ControlTextArea()
        self._output.readonly = True
        self._qview = ControlList("Queue", select_entire_row=True)
        self._qview.cell_double_clicked_event = self.__show_oview
        self._qview.readonly = True
        self._qview.horizontal_headers = ["Player 1", "Player 2", "Round"]

        # Button
        self._submit_button = ControlButton("Submit")
        self._submit_button.value = self.__on_submit

        self._timestamp_button = ControlButton("Record Timestamp")
        self._timestamp_button.value = self.__on_timestamp

        # Title Formats
        for f in consts.title_format:
            self._title_format += f

        # Form Layout
        self.formset = [
            {
                "-Match": [
                    "_file",
                    (" ", "_mprefix", "_mtype", "_msuffix", " "),
                    (" ", "_p1_sponsor", "_p1", " "),
                    (" ", "_p1char", " "),
                    (" ", "_p2_sponsor", "_p2", " "),
                    (" ", "_p2char", " "),
                    (" ", "_timestamp_button", " "),
                ],
                "-Status-": ["_output", "=", "_qview"],
                "Event-": [
                    "_privacy",
                    "_title_format",
                    ("_ename", "_ename_min"),
                    "_pID",
                    "_bracket",
                    "_tags",
                    "_description",
                ],
            },
            (" ", "_submit_button", " "),
        ]

        # Main Menu Layout
        self.mainmenu = [{
            "Settings": [
                {
                    "YouTube Log Out": self.__reset_yt_cred
                },
                {
                    "Toggle OBS Hook": self.__show_obs_form
                },
                {
                    "Toggle SA Hook": self.__show_sa_form
                },
                {
                    "Toggle SC Hook": self.__show_sc_form
                },
                {
                    "Toggle Streameta Hook": self.__show_sm_form
                },
                {
                    "About": self.__about_info
                },
            ],
            "Save/Clear": [
                {
                    "Save Form": self.__save_form
                },
                {
                    "Clear Match Values": self.__reset_match
                },
                {
                    "Clear Event Values": self.__reset_event
                },
                {
                    "Clear All": self.__reset_forms
                },
            ],
            "Queue": [
                {
                    "Toggle Uploads": utils.toggle_worker
                },
                {
                    "Save Queue": self.__save_queue
                },
                {
                    "Load Queue": self.__load_queue
                },
                {
                    "Toggle Save on Submit": self.__save_on_submit
                },
            ],
            "History": [{
                "Show History": self.__show_hview
            }],
            "Characters": [
                {
                    "Melee": self.__melee_chars
                },
                {
                    "Ultimate": self.__ultimate_chars
                },
                {
                    "64": self.__64_chars
                },
                {
                    "Rivals": self.__rivals_chars
                },
                {
                    "Splatoon": self.__splatoon_chars
                },
                {
                    "Strive": self.__strive_chars
                },
                {
                    "NASB": self.__nasb_chars
                },
                {
                    "Custom": self.__custom_chars
                },
            ],
        }]

        # Add ControlCombo values
        for t in consts.match_types:
            self._mtype += t
        for t in ("unlisted", "public", "private"):
            self._privacy += t

        # Set placeholder text
        self._ename_min.form.lineEdit.setPlaceholderText(
            "Shortened Event Name")
        self._p1_sponsor.form.lineEdit.setPlaceholderText("Sponsor Tag")
        self._p2_sponsor.form.lineEdit.setPlaceholderText("Sponsor Tag")
        self._p1.form.lineEdit.setPlaceholderText("P1 Name")
        self._p2.form.lineEdit.setPlaceholderText("P2 Name")
        self._mprefix.form.lineEdit.setPlaceholderText("Round Prefix")
        self._msuffix.form.lineEdit.setPlaceholderText("Round Suffix")
        self._bracket.form.lineEdit.setPlaceholderText("Include https://")
        self._tags.form.lineEdit.setPlaceholderText("Separate with commas")
        self._pID.form.lineEdit.setPlaceholderText(
            "Accepts full YT link or a new playlist title")

        # For pulling characters
        self.__p1chars = []
        self.__p2chars = []

        # Set character list
        self.game_chars = {
            "64": self.__64_chars,
            "melee": self.__melee_chars,
            "ult": self.__ultimate_chars,
            "rivals": self.__rivals_chars,
            "splatoon": self.__splatoon_chars,
            "strive": self.__strive_chars,
            "custom": self.__custom_chars,
        }
        self.game_chars[consts.game]()

        # Stream Control
        self._sc = None
        self.__sc_mapping = {  # defaults are based on Recursion's setup
            "file": "",
            "p1_name": "p1_name",
            "p2_name": "p2_name",
            "p1_char": "p1_char",
            "p2_char": "p2_char",
            "p1_sponsor": "p1_sponsor",
            "p2_sponsor": "p2_sponsor",
            "mtype": "event_round",
            "mprefix": "event_bracket",
        }

        # Streameta
        self._sm = None
        self._smf = ControlText()
        self._smf.value = ""

        # Define the mapping of the form values json to form fields
        self._form_fields = {
            "ename": self._ename,
            "pID": self._pID,
            "mtype": self._mtype,
            "p1": self._p1,
            "p2": self._p2,
            "p1char": self._p1char,
            "p2char": self._p2char,
            "bracket": self._bracket,
            "file": self._file,
            "tags": self._tags,
            "msuffix": self._msuffix,
            "mprefix": self._mprefix,
            "p1sponsor": self._p1_sponsor,
            "p2sponsor": self._p2_sponsor,
            "privacy": self._privacy,
            "description": self._description,
            "ename_min": self._ename_min,
            "title_format": self._title_format,
            "streameta_url": self._smf,
        }

        # Get latest values from form_values.txt
        if consts.start_queue:
            self.__load_queue()
        else:
            self.__load_form()
Пример #9
0
    def __init__(self):
        try:  # check if the user can update the app
            latest_version = requests.get('https://pypi.org/pypi/FRCUploader/json').json()['info']['version']
            if sv(latest_version) > sv(consts.__version__):  # prevents messages when developing
                if "linux" in sys.platform:
                    self.message(f"Current Version: {consts.__version__}\nVersion {latest_version} is available.\n You can update with this command: pip3 install -U frcuploader=={latest_version}", title="FRCUploader")
                else:
                    resp = self.question(f"Current Version: {consts.__version__}\nVersion {latest_version} is available. Would you like to update?", title="FRCUploader")
                    if resp == "yes":
                        subprocess.call(('pip3', 'install', '-I', f'frcuploader=={latest_version}'))
                        self.message("You can now restart the app to use the new version", title="FRCUploader")
        except Exception as e:
            print(e)
        super(FRC_Uploader, self).__init__("FRC YouTube Uploader")

        # Redirct print output
        sys.stdout = EmittingStream(textWritten=self.write_print)

        # Redirect error output to window, console, and file
        sys.stderr = EmittingStream(textWritten=self.write_err)

        # Queue
        self._queue = Queue()
        self._queueref = []

        # Create form fields
        # Event Values
        self._where = ControlDir(" Match Files Location")
        self._newest = ControlCheckBox("Get Newest File")
        self._sendto = ControlDir(" Move Files To")
        self._prodteam = ControlText(" Production Team")
        self._twit = ControlText("Twitter Handle")
        self._fb = ControlText("Facebook Name")
        self._weblink = ControlText(" Website Link")
        self._ename = ControlText("Event Name")
        self._ecode = ControlText("Event Code")
        self._pID = ControlText(" Playlist ID")
        self._tbaID = ControlText("TBA ID")
        self._tbaSecret = ControlText("TBA Secret")
        self._privacy = ControlCombo("Video Privacy Status")
        self._description = ControlTextArea(" Video Description")
        self._description.add_popup_menu_option("Reset", self.__reset_descrip_event)

        # Match Values
        self._mcode = ControlText("Match Code", visible=False, helptext="READ THE INSTRUCTIONS TO FIND OUT HOW TO USE THIS!")
        self._mnum = ControlNumber("Match Number", minimum=1, maximum=500)
        self._mtype = ControlCombo("Match Type")
        self._tiebreak = ControlCheckBox("Tiebreaker")
        self._tba = ControlCheckBox("Use TBA")
        self._replay = ControlCheckBox("Replay")
        self._ceremonies = ControlCombo("Ceremonies")
        self._eday = ControlCombo("Event Day")
        self._end = ControlNumber("Last Match Number", minimum=0, maximum=500)

        # Output Box
        self._output = ControlTextArea()
        self._output.readonly = True
        self._qview = ControlList("Queue", select_entire_row=True)
        self._qview.cell_double_clicked_event = self.__ignore_job
        self._qview.readonly = True
        self._qview.horizontal_headers = ["Event Code", "Match Type", "Match #"]

        # Button
        self._button = ControlButton('Submit')
        self._ascrollbutton = ControlButton("Toggle Scroll")
        self._autoscroll = True

        # Form Layout
        self.formset = [{
            "-Match Values":
            [(' ', "_mcode", ' '), (' ', "_mnum", ' '), (' ', "_mtype", ' '),
             (' ', "_tiebreak", "_tba", "_replay", ' '), (' ', "_ceremonies", ' '),
             (' ', "_eday", ' '), (' ', "_end", ' ')],
            "-Status Output-":
            ["_output", (' ', "_ascrollbutton", ' '), "=", "_qview"],
            "Event Values-": [("_where", "_newest"), "_sendto", ("_prodteam", "_twit", "_fb"),
                              ("_weblink", "_ename", "_ecode"),
                              ("_pID", "_tbaID", "_tbaSecret"), ("_privacy", " "), "_description"]
        }, (' ', '_button', ' ')]

        # Main Menu Layout
        self.mainmenu = [{
            'Settings': [{'Youtube Log Out': self.__reset_cred}, {'Show/Hide Match Code': self.__toggle_match_code}],
            'Save/Clear': [{'Save Form': self.__save_form}, {'Clear Form': self.__reset_form}],
            'Queue': [{'Toggle Uploads': self.__toggle_worker}, {'Save Queue': self.__save_queue}, {'Load Queue': self.__load_queue}]}]

        # Set TBA check
        self._tba.value = True

        # Set Default Text
        self._tbaID.value = "Go to thebluealliance.com/request/apiwrite to get keys"
        self._tbaSecret.value = "Go to thebluealliance.com/request/apiwrite to get keys"
        self._description.value = consts.DEFAULT_DESCRIPTION
        self._mcode.value = "0"
        self._mnum.value = 1

        # Add ControlCombo values
        for t in consts.VALID_PRIVACY_STATUSES:
            self._privacy += t
        self._mtype += ("Qualifications", "qm")
        self._mtype += ("Quarterfinals", "qf")
        self._mtype += ("Semifinals", "sf")
        self._mtype += ("Finals", "f1m")
        self._ceremonies += ("None", 0)
        self._ceremonies += ("Opening Ceremonies", 1)
        self._ceremonies += ("Alliance Selection", 2)
        self._ceremonies += ("Closing Ceremonies", 3)
        self._ceremonies += ("Highlight Reel", 4)
        self._eday += ("Ignore", 0)
        self._eday += ("1", 1)
        self._eday += ("2", 2)
        self._eday += ("3", 3)

        # Define the button action
        self._button.value = self.__button_action
        self._ascrollbutton.value = self.__togglescroll

        self.testval = 0

        self._form_fields = (
            self._where,
            self._prodteam,
            self._twit,
            self._fb,
            self._weblink,
            self._ename,
            self._ecode,
            self._pID,
            self._tbaID,
            self._tbaSecret,
            self._description,
            self._mcode,
            self._mnum,
            self._mtype,
            self._tiebreak,
            self._tba,
            self._ceremonies,
            self._eday,
            self._end,
            self._newest,
            self._privacy,
            self._sendto,
        )
        self.__load_form()
Пример #10
0
class FRC_Uploader(BaseWidget):
    """
    GUI constructor.
    Create the GUI using pyforms_lite.start_app(FRC_Uploader)
    """

    def __init__(self):
        try:  # check if the user can update the app
            latest_version = requests.get('https://pypi.org/pypi/FRCUploader/json').json()['info']['version']
            if sv(latest_version) > sv(consts.__version__):  # prevents messages when developing
                if "linux" in sys.platform:
                    self.message(f"Current Version: {consts.__version__}\nVersion {latest_version} is available.\n You can update with this command: pip3 install -U frcuploader=={latest_version}", title="FRCUploader")
                else:
                    resp = self.question(f"Current Version: {consts.__version__}\nVersion {latest_version} is available. Would you like to update?", title="FRCUploader")
                    if resp == "yes":
                        subprocess.call(('pip3', 'install', '-I', f'frcuploader=={latest_version}'))
                        self.message("You can now restart the app to use the new version", title="FRCUploader")
        except Exception as e:
            print(e)
        super(FRC_Uploader, self).__init__("FRC YouTube Uploader")

        # Redirct print output
        sys.stdout = EmittingStream(textWritten=self.write_print)

        # Redirect error output to window, console, and file
        sys.stderr = EmittingStream(textWritten=self.write_err)

        # Queue
        self._queue = Queue()
        self._queueref = []

        # Create form fields
        # Event Values
        self._where = ControlDir(" Match Files Location")
        self._newest = ControlCheckBox("Get Newest File")
        self._sendto = ControlDir(" Move Files To")
        self._prodteam = ControlText(" Production Team")
        self._twit = ControlText("Twitter Handle")
        self._fb = ControlText("Facebook Name")
        self._weblink = ControlText(" Website Link")
        self._ename = ControlText("Event Name")
        self._ecode = ControlText("Event Code")
        self._pID = ControlText(" Playlist ID")
        self._tbaID = ControlText("TBA ID")
        self._tbaSecret = ControlText("TBA Secret")
        self._privacy = ControlCombo("Video Privacy Status")
        self._description = ControlTextArea(" Video Description")
        self._description.add_popup_menu_option("Reset", self.__reset_descrip_event)

        # Match Values
        self._mcode = ControlText("Match Code", visible=False, helptext="READ THE INSTRUCTIONS TO FIND OUT HOW TO USE THIS!")
        self._mnum = ControlNumber("Match Number", minimum=1, maximum=500)
        self._mtype = ControlCombo("Match Type")
        self._tiebreak = ControlCheckBox("Tiebreaker")
        self._tba = ControlCheckBox("Use TBA")
        self._replay = ControlCheckBox("Replay")
        self._ceremonies = ControlCombo("Ceremonies")
        self._eday = ControlCombo("Event Day")
        self._end = ControlNumber("Last Match Number", minimum=0, maximum=500)

        # Output Box
        self._output = ControlTextArea()
        self._output.readonly = True
        self._qview = ControlList("Queue", select_entire_row=True)
        self._qview.cell_double_clicked_event = self.__ignore_job
        self._qview.readonly = True
        self._qview.horizontal_headers = ["Event Code", "Match Type", "Match #"]

        # Button
        self._button = ControlButton('Submit')
        self._ascrollbutton = ControlButton("Toggle Scroll")
        self._autoscroll = True

        # Form Layout
        self.formset = [{
            "-Match Values":
            [(' ', "_mcode", ' '), (' ', "_mnum", ' '), (' ', "_mtype", ' '),
             (' ', "_tiebreak", "_tba", "_replay", ' '), (' ', "_ceremonies", ' '),
             (' ', "_eday", ' '), (' ', "_end", ' ')],
            "-Status Output-":
            ["_output", (' ', "_ascrollbutton", ' '), "=", "_qview"],
            "Event Values-": [("_where", "_newest"), "_sendto", ("_prodteam", "_twit", "_fb"),
                              ("_weblink", "_ename", "_ecode"),
                              ("_pID", "_tbaID", "_tbaSecret"), ("_privacy", " "), "_description"]
        }, (' ', '_button', ' ')]

        # Main Menu Layout
        self.mainmenu = [{
            'Settings': [{'Youtube Log Out': self.__reset_cred}, {'Show/Hide Match Code': self.__toggle_match_code}],
            'Save/Clear': [{'Save Form': self.__save_form}, {'Clear Form': self.__reset_form}],
            'Queue': [{'Toggle Uploads': self.__toggle_worker}, {'Save Queue': self.__save_queue}, {'Load Queue': self.__load_queue}]}]

        # Set TBA check
        self._tba.value = True

        # Set Default Text
        self._tbaID.value = "Go to thebluealliance.com/request/apiwrite to get keys"
        self._tbaSecret.value = "Go to thebluealliance.com/request/apiwrite to get keys"
        self._description.value = consts.DEFAULT_DESCRIPTION
        self._mcode.value = "0"
        self._mnum.value = 1

        # Add ControlCombo values
        for t in consts.VALID_PRIVACY_STATUSES:
            self._privacy += t
        self._mtype += ("Qualifications", "qm")
        self._mtype += ("Quarterfinals", "qf")
        self._mtype += ("Semifinals", "sf")
        self._mtype += ("Finals", "f1m")
        self._ceremonies += ("None", 0)
        self._ceremonies += ("Opening Ceremonies", 1)
        self._ceremonies += ("Alliance Selection", 2)
        self._ceremonies += ("Closing Ceremonies", 3)
        self._ceremonies += ("Highlight Reel", 4)
        self._eday += ("Ignore", 0)
        self._eday += ("1", 1)
        self._eday += ("2", 2)
        self._eday += ("3", 3)

        # Define the button action
        self._button.value = self.__button_action
        self._ascrollbutton.value = self.__togglescroll

        self.testval = 0

        self._form_fields = (
            self._where,
            self._prodteam,
            self._twit,
            self._fb,
            self._weblink,
            self._ename,
            self._ecode,
            self._pID,
            self._tbaID,
            self._tbaSecret,
            self._description,
            self._mcode,
            self._mnum,
            self._mtype,
            self._tiebreak,
            self._tba,
            self._ceremonies,
            self._eday,
            self._end,
            self._newest,
            self._privacy,
            self._sendto,
        )
        self.__load_form()

    def __togglescroll(self):
        self._autoscroll = False if self._autoscroll else True

    def __button_action(self):
        """Manipulates and transforms data from the forms into usable
           data that can be used for uploading videos"""
        options = Namespace()
        options.where = self._where.value
        options.prodteam = self._prodteam.value
        options.twit = self._twit.value
        options.fb = self._fb.value
        options.weblink = self._weblink.value
        options.ename = self._ename.value
        options.ecode = self._ecode.value
        f = self._pID.value.find("PL")
        self._pID.value = self._pID.value[f:f + 34]
        options.pID = self._pID.value
        options.tbaID = self._tbaID.value
        options.tbaSecret = self._tbaSecret.value
        if not consts.trusted and options.tbaID and options.tbaSecret and options.ecode:
            consts.tba.update_trusted(options.tbaID, options.tbaSecret, options.ecode)
        options.description = self._description.value
        options.mcode = self._mcode.value
        options.mnum = int(self._mnum.value)
        options.mtype = self._mtype.value
        options.tiebreak = deepcopy(self._tiebreak.value)
        options.tba = deepcopy(self._tba.value)
        options.ceremonies = self._ceremonies.value
        options.eday = self._eday.value
        options.end = 0
        options.replay = self._replay.value
        self._replay.value = False
        options.newest = deepcopy(self._newest.value)
        if options.newest:
            files = list(reversed([f for f in os.listdir(options.where) if os.path.isfile(os.path.join(options.where, f)) and not f.startswith('.') and any(f.endswith(z) for z in consts.rec_formats)]))
            options.file = max([os.path.join(options.where, f) for f in files], key=os.path.getmtime)
            for f in files:
                if f in options.file:
                    options.filebasename = f
        options.privacy = self._privacy.value
        options.sendto = self._sendto.value
        options.ignore = False
        if not int(self._end.value):
            if options.ceremonies:
                self._qview += (options.ecode, consts.cerem[options.ceremonies], "N/A")
            else:
                self._qview += (options.ecode, options.mtype, options.mnum)
        elif not options.newest:
            for r in range(options.mnum, int(self._end.value)):
                self._qview += (options.ecode, options.mtype, options.mnum)
                self._queue.put(options)
                self._queueref.append(options)
                self._qview.resize_rows_contents()
                options = deepcopy(options)
                options.mnum += 1
        else:
            print("Using Last Match Number and Get Newest File together is not supported")
            print(f"Will fallback to just uploading the newest file for mnum {options.mnum}")
            self._end.value = 0
        if int(self._end.value):
            self._qview += (options.ecode, options.mtype, options.mnum)
        self._queue.put(options)
        self._queueref.append(options)
        self._qview.resize_rows_contents()
        if consts.firstrun:
            thr = threading.Thread(target=self.__worker)
            thr.daemon = True
            thr.start()
            consts.firstrun = False
        if not self._ceremonies.value:
            if not int(self._end.value):
                self._mnum.value = self._mnum.value + 1
            else:
                self._mnum.value = self._end.value + 1
                self._end.value = 0
        elif self._ceremonies.value == 2:
            self._mnum.value = 1
            self._mtype.value = "qf"
        if self._mtype.value == "qm" and self._tiebreak.value:
            self._tiebreak.value = False
        self.__save_form()

    def write_print(self, text):
        self._output._form.plainTextEdit.insertPlainText(text)
        if self._autoscroll:
            self._output._form.plainTextEdit.moveCursor(QtGui.QTextCursor.End)
        if sys.__stdout__:
            print(text, file=sys.__stdout__, end='')

    def write_err(self, text):
        self._output._form.plainTextEdit.insertPlainText(text)
        if self._autoscroll:
            self._output._form.plainTextEdit.moveCursor(QtGui.QTextCursor.End)
        if sys.__stdout__:
            print(text, file=sys.__stdout__, end='')
        with open(consts.log_file, "a") as f:
            f.write(text)

    def __worker(self):
        while not consts.stop_thread:
            options = self._queue.get()
            if not options.ignore:
                options.then = datetime.now()
                utils.init(options)
                self._qview -= 0
                self._queueref.pop(0)
            self._queue.task_done()
        else:
            print("Uploads are stopped")

    def __toggle_worker(self):
        if not consts.stop_thread:
            print("Stopping Uploads")
            consts.stop_thread = True
            consts.firstrun = False
        else:
            print("Ready to Upload")
            consts.stop_thread = False
            consts.firstrun = True

    def __save_form(self, options=[]):
        row = [None] * (len(self._form_fields) + 1)
        if options:
            f = options.pID.find("PL")
            options.pID = options.pID[f:f + 34]
            row[0] = deepcopy(options.where)
            row[1] = deepcopy(options.prodteam)
            row[2] = deepcopy(options.twit)
            row[3] = deepcopy(options.fb)
            row[4] = deepcopy(options.weblink)
            row[5] = deepcopy(options.ename)
            row[6] = deepcopy(options.ecode)
            row[7] = deepcopy(options.pID)
            row[8] = deepcopy(options.tbaID)
            row[9] = deepcopy(options.tbaSecret)
            row[10] = deepcopy(options.description)
            row[11] = deepcopy(options.mcode)
            row[12] = deepcopy(options.mnum)
            row[13] = deepcopy(options.mtype)
            row[14] = deepcopy(options.tiebreak)
            row[15] = deepcopy(options.tba)
            row[16] = deepcopy(options.ceremonies)
            row[17] = deepcopy(options.eday)
            row[18] = deepcopy(options.end)
            row[19] = deepcopy(options.newest)
            row[20] = deepcopy(options.privacy)
            row[21] = deepcopy(options.sendto)
        else:
            f = self._pID.value.find("PL")
            self._pID.value = self._pID.value[f:f + 34]
            for i, var in zip(range(len(self._form_fields) + 1), self._form_fields):
                row[i] = deepcopy(var.value)
        with open(consts.form_values, 'w') as f:
                f.write(json.dumps(row))
        return row

    def __load_form(self):
        try:
            with open(consts.form_values, "r") as f:
                values = json.loads(f.read())
                for val, var in zip(values, self._form_fields):
                    if isinstance(val, bool):
                        var.value = True if val else False
                    elif val:
                        var.value = val
        except (IOError, OSError, StopIteration, json.decoder.JSONDecodeError) as e:
            print(f"No {consts.abbrv}_form_values.json to read from, continuing with default values")

    def __save_queue(self):
        if os.path.exists(consts.queue_values):
            resp = self.question(f"A queue already exists would you like to overwrite it?\nIt was last modified on {datetime.utcfromtimestamp(int(os.path.getmtime(consts.queue_values))).strftime('%Y-%m-%d')}")
            if resp == "yes":
                with open(consts.queue_values, "wb") as f:
                    f.write(pickle.dumps(self._queueref))
                print("Saved Queue, you can now close the program")
            elif resp == "no":
                resp = self.question("Would you like to add onto the end of that queue?")
                if resp == "yes":
                    queueref = None
                    with open(consts.queue_values, "rb") as f:
                        queueref = pickle.load(f)
                    queueref.extend(self._queueref)
                    with open(consts.queue_values, "wb") as f:
                        f.write(pickle.dumps(queueref))
                    print("Saved Queue, you can now close the program")
                else:
                    self.message("Not saving queue")

    def __load_queue(self):
        if self._queueref:
            resp = self.question("Would you like to add to the existing queue?\nItems will be added to the front of the queue.")
            if resp == "yes":
                try:
                    with open(consts.queue_values, "rb") as f:
                        queueref = pickle.load(f)
                    queueref.extend(self._queueref)
                    self._queueref = queueref
                    self._qview.clear()
                    self._qview.horizontal_headers = ["Event Code", "Match Type", "Match #"]
                    for options in self._queueref:
                        if options.ceremonies:
                            self._qview += (options.ecode, consts.cerem[options.ceremonies], "N/A")
                        else:
                            self._qview += (options.ecode, options.mtype, options.mnum)
                        self._queue.put(options)
                        self._qview.resize_rows_contents()
                        self.__save_form(options)
                except Exception as e:
                    print("You need to save a queue before loading a queue")
                    return
        else:
            try:
                with open(consts.queue_values, "rb") as f:
                    self._queueref = pickle.load(f)
                for options in self._queueref:
                    if options.ceremonies:
                        self._qview += (options.ecode, consts.cerem[options.ceremonies], "N/A")
                    else:
                        self._qview += (options.ecode, options.mtype, options.mnum)
                    self._queue.put(options)
                    self._qview.resize_rows_contents()
                    self.__save_form(options)
            except Exception as e:
                print("You need to save a queue before loading a queue")
                return

        resp = self.question("Do you want to start uploading?")
        if resp == "yes":
            thr = threading.Thread(target=self.__worker)
            thr.daemon = True
            consts.firstrun = False
            consts.stop_thread = False
            thr.start()

    def __reset_form(self):
        with open(consts.form_values, "w+") as f:
            f.write(json.dumps([]))
        self._tbaID.value = "Go to thebluealliance.com/request/apiwrite to get keys"
        self._tbaSecret.value = "Go to thebluealliance.com/request/apiwrite to get keys"
        self._description.value = consts.DEFAULT_DESCRIPTION
        self._mcode.value = "0"
        self._mnum.value = 1
        self._end.value = 0
        self._mtype.value = "qm"
        self._ceremonies.value = 0
        self._eday.value = 0
        self._tba.value = True
        self._where.value = ""
        self._sendto.value = ""
        self._prodteam.value = ""
        self._twit.value = ""
        self._fb.value = ""
        self._weblink.value = ""
        self._ename.value = ""
        self._ecode.value = ""
        self._pID.value = ""

    def __reset_cred(self):
        title = consts.youtube.channels().list(part='snippet', mine=True).execute()
        title = title['items'][0]['snippet']['title']
        resp = self.question(f"You are currently logged into {title}\nWould you like to log out?", title="FRCUploader")
        if resp == "yes":
            os.remove(os.path.join(os.path.expanduser("~"), ".frc-oauth2-spreadsheet.json"))
            os.remove(os.path.join(os.path.expanduser("~"), ".frc-oauth2-youtube.json"))
            sys.exit(0)

    def __reset_descrip_event(self):
        self._description.value = consts.DEFAULT_DESCRIPTION

    def __ignore_job(self, row, column):
        self._qview -= row
        self._queueref[row].ignore = True
        self._queueref.pop(row)

    def __toggle_match_code(self):
        if self._mcode.visible:
            self._mcode.hide()
        else:
            self._mcode.show()