1
0
Fork 0
mirror of synced 2024-06-17 01:54:46 +12:00

Merge pull request #139 from Dummerle/add_ubi_activation

Add Ubisoft activation in legendary settings
This commit is contained in:
Dummerle 2021-12-13 22:12:54 +01:00 committed by GitHub
commit f12c633211
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 314 additions and 130 deletions

View file

@ -22,27 +22,28 @@ AppDir:
version: 1.7.0
exec: usr/bin/python3
exec_args: $APPDIR/usr/src/__main__.py $@
apt:d
arch: amd64
allow_unauthenticated: true
sources:
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy main restricted
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy-updates main restricted
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy universe
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy-updates universe
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy multiverse
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy-updates multiverse
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy-backports main restricted
universe multiverse
- sourceline: deb http://security.ubuntu.com/ubuntu groovy-security main restricted
- sourceline: deb http://security.ubuntu.com/ubuntu groovy-security universe
- sourceline: deb http://security.ubuntu.com/ubuntu groovy-security multiverse
include:
- python3
- python3-distutils
- python3-pyqt5
- python3-psutil
- python3-requests
apt:
arch: amd64
allow_unauthenticated: true
sources:
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy main restricted
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy-updates main restricted
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy universe
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy-updates universe
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy multiverse
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy-updates multiverse
- sourceline: deb http://de.archive.ubuntu.com/ubuntu/ groovy-backports main restricted
universe multiverse
- sourceline: deb http://security.ubuntu.com/ubuntu groovy-security main restricted
- sourceline: deb http://security.ubuntu.com/ubuntu groovy-security universe
- sourceline: deb http://security.ubuntu.com/ubuntu groovy-security multiverse
include:
- python3
- python3-distutils
- python3-pyqt5
- python3-psutil
- python3-requests
runtime:
env:

View file

@ -78,6 +78,6 @@ if __name__ == '__main__':
# insert raw legendary submodule
sys.path.insert(0, os.path.join(pathlib.Path(__file__).parent.absolute(), "legendary"))
# insert source directory
sys.path.insert(0, str(pathlib.Path(__file__).parents[2].absolute()))
sys.path.insert(0, str(pathlib.Path(__file__).parents[1].absolute()))
main()

View file

@ -5,6 +5,7 @@ from typing import Tuple
from PyQt5.QtWidgets import QSizePolicy, QWidget, QFileDialog, QMessageBox
import rare.shared as shared
from rare.components.tabs.settings.ubisoft_activation import UbiActivationHelper
from rare.ui.components.tabs.settings.legendary import Ui_LegendarySettings
from rare.utils.extra_widgets import PathEdit, IndicatorLineEdit
from rare.utils.utils import get_size
@ -59,6 +60,8 @@ class LegendarySettings(QWidget, Ui_LegendarySettings):
)
self.locale_layout.addWidget(self.locale_edit)
self.ubi_helper = UbiActivationHelper(self.ubisoft_gb)
@staticmethod
def locale_edit_cb(text: str) -> Tuple[bool, str]:
if text:
@ -111,7 +114,7 @@ class LegendarySettings(QWidget, Ui_LegendarySettings):
self.core.lgd.config.set("Legendary", "disable_https", str(bool(checked)).lower())
self.core.lgd.save_config()
def cleanup(self, keep_manifests):
def cleanup(self, keep_manifests: bool):
before = self.core.lgd.get_dir_size()
logger.debug('Removing app metadata...')
app_names = set(g.app_name for g in self.core.get_assets(update_assets=False))

View file

@ -0,0 +1,181 @@
import time
import webbrowser
from logging import getLogger
from PyQt5.QtCore import QObject, pyqtSignal, QRunnable, QThreadPool, QSize
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QSizePolicy, QPushButton
from qtawesome import icon
from legendary.models.game import Game
from rare import shared
logger = getLogger("Ubisoft")
class Signals(QObject):
worker_finished = pyqtSignal(set, set, str)
linked = pyqtSignal(str)
class UbiGetInfoWorker(QRunnable):
def __init__(self):
super(UbiGetInfoWorker, self).__init__()
self.signals = Signals()
self.setAutoDelete(True)
def run(self) -> None:
try:
external_auths = shared.core.egs.get_external_auths()
for ext_auth in external_auths:
if ext_auth['type'] != 'ubisoft':
continue
ubi_account_id = ext_auth['externalAuthId']
break
else:
self.signals.worker_finished.emit(set(), set(), "")
return
uplay_keys = shared.core.egs.store_get_uplay_codes()
key_list = uplay_keys['data']['PartnerIntegration']['accountUplayCodes']
redeemed = {k['gameId'] for k in key_list if k['redeemedOnUplay']}
entitlements = shared.core.egs.get_user_entitlements()
entitlements = {i['entitlementName'] for i in entitlements}
self.signals.worker_finished.emit(redeemed, entitlements, ubi_account_id)
except Exception as e:
logger.error(str(e))
self.signals.worker_finished.emit(set(), set(), "error")
class UbiConnectWorker(QRunnable):
def __init__(self, ubi_account_id, partner_link_id):
super(UbiConnectWorker, self).__init__()
self.signals = Signals()
self.setAutoDelete(True)
self.ubi_account_id = ubi_account_id
self.partner_link_id = partner_link_id
def run(self) -> None:
if not self.ubi_account_id: # debug
time.sleep(2)
self.signals.linked.emit("")
return
try:
shared.core.egs.store_claim_uplay_code(self.ubi_account_id, self.partner_link_id)
shared.core.egs.store_redeem_uplay_codes(self.ubi_account_id)
except Exception as e:
self.signals.linked.emit(str(e))
return
else:
self.signals.linked.emit("")
class UbiLinkWidget(QWidget):
def __init__(self, game: Game, ubi_account_id):
super(UbiLinkWidget, self).__init__()
self.setLayout(QHBoxLayout())
self.game = game
self.ubi_account_id = ubi_account_id
self.title_label = QLabel(game.app_title)
self.layout().addWidget(self.title_label)
self.ok_indicator = QLabel()
self.ok_indicator.setPixmap(icon("fa.info-circle", color="grey").pixmap(20, 20))
self.ok_indicator.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred)
self.layout().addWidget(self.ok_indicator)
self.link_button = QPushButton(self.tr("Redeem to Ubisoft") + ": Test" if shared.args.debug else "")
self.layout().addWidget(self.link_button)
self.link_button.clicked.connect(self.activate)
def activate(self):
self.link_button.setDisabled(True)
# self.ok_indicator.setPixmap(icon("mdi.loading", color="grey").pixmap(20, 20))
self.ok_indicator.setPixmap(icon("mdi.transit-connection-horizontal", color="grey").pixmap(20, 20))
if shared.args.debug:
worker = UbiConnectWorker(None, None)
else:
worker = UbiConnectWorker(self.ubi_account_id, self.game.partner_link_id)
worker.signals.linked.connect(self.worker_finished)
QThreadPool.globalInstance().start(worker)
def worker_finished(self, error):
if not error:
self.ok_indicator.setPixmap(icon("ei.ok-circle", color="green").pixmap(QSize(20, 20)))
self.link_button.setDisabled(True)
self.link_button.setText(self.tr("Already activated"))
else:
self.ok_indicator.setPixmap(icon("fa.info-circle", color="red").pixmap(QSize(20, 20)))
self.ok_indicator.setToolTip(error)
self.link_button.setText(self.tr("Try again"))
self.link_button.setDisabled(False)
class UbiActivationHelper(QObject):
def __init__(self, widget: QWidget):
super(UbiActivationHelper, self).__init__()
self.widget = widget
self.core = shared.core
self.thread_pool = QThreadPool.globalInstance()
worker = UbiGetInfoWorker()
worker.signals.worker_finished.connect(self.show_ubi_games)
self.thread_pool.start(worker)
def show_ubi_games(self, redeemed: set, entitlements: set, ubi_account_id: str):
if not redeemed and ubi_account_id != "error":
logger.error('No linked ubisoft account found! Link your accounts via your browser and try again.')
self.widget.layout().addWidget(
QLabel(self.tr("Your account is not linked with Ubisoft. Please link your account first")))
open_browser_button = QPushButton(self.tr("Open link page"))
open_browser_button.clicked.connect(lambda: webbrowser.open("https://www.epicgames.com/id/link/ubisoft"))
self.widget.layout().addWidget(open_browser_button)
return
elif ubi_account_id == "error":
self.widget.layout().addWidget(QLabel(self.tr("An error occurred")))
return
games = self.core.get_game_list(False)
uplay_games = []
activated = 0
for game in games:
for dlc_data in game.metadata.get('dlcItemList', []):
if dlc_data['entitlementName'] not in entitlements:
continue
try:
app_name = dlc_data['releaseInfo'][0]['appId']
except (IndexError, KeyError):
app_name = 'unknown'
dlc_game = Game(app_name=app_name, app_title=dlc_data['title'], metadata=dlc_data)
if dlc_game.partner_link_type != 'ubisoft':
continue
if dlc_game.partner_link_id in redeemed:
continue
uplay_games.append(dlc_game)
if game.partner_link_type != "ubisoft":
continue
if game.partner_link_id in redeemed:
activated += 1
continue
uplay_games.append(game)
if not uplay_games:
if activated >= 1:
self.widget.layout().addWidget(
QLabel(self.tr("All your Ubisoft games have already been activated")))
else:
self.widget.layout().addWidget(QLabel(self.tr("You don't own any Ubisoft games")))
if shared.args.debug:
widget = UbiLinkWidget(Game(app_name="Test", app_title="This is a test game"), ubi_account_id)
self.widget.layout().addWidget(widget)
return
logger.info(f'Found {len(uplay_games)} game(s) to redeem')
for game in uplay_games:
widget = UbiLinkWidget(game, ubi_account_id)
self.widget.layout().addWidget(widget)

@ -1 +1 @@
Subproject commit ab7d209d5318f862d20081724383f523b6de4c7b
Subproject commit d371c0b3c48a422ff7e6c966af649a1502300c2d

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'rare/ui/components/tabs/settings/legendary.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
@ -14,10 +14,39 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_LegendarySettings(object):
def setupUi(self, LegendarySettings):
LegendarySettings.setObjectName("LegendarySettings")
LegendarySettings.resize(552, 268)
LegendarySettings.resize(564, 374)
LegendarySettings.setWindowTitle("LegendarySettings")
self.settings_layout = QtWidgets.QHBoxLayout(LegendarySettings)
self.settings_layout.setObjectName("settings_layout")
self.gridLayout = QtWidgets.QGridLayout(LegendarySettings)
self.gridLayout.setObjectName("gridLayout")
self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setObjectName("right_layout")
self.locale_group = QtWidgets.QGroupBox(LegendarySettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.locale_group.sizePolicy().hasHeightForWidth())
self.locale_group.setSizePolicy(sizePolicy)
self.locale_group.setObjectName("locale_group")
self.locale_layout = QtWidgets.QVBoxLayout(self.locale_group)
self.locale_layout.setObjectName("locale_layout")
self.right_layout.addWidget(self.locale_group)
self.cleanup_group = QtWidgets.QGroupBox(LegendarySettings)
self.cleanup_group.setObjectName("cleanup_group")
self.cleanup_layout = QtWidgets.QVBoxLayout(self.cleanup_group)
self.cleanup_layout.setObjectName("cleanup_layout")
self.clean_keep_manifests_button = QtWidgets.QPushButton(self.cleanup_group)
self.clean_keep_manifests_button.setObjectName("clean_keep_manifests_button")
self.cleanup_layout.addWidget(self.clean_keep_manifests_button)
self.clean_button = QtWidgets.QPushButton(self.cleanup_group)
self.clean_button.setObjectName("clean_button")
self.cleanup_layout.addWidget(self.clean_button)
self.right_layout.addWidget(self.cleanup_group)
self.gridLayout.addLayout(self.right_layout, 0, 1, 1, 1)
self.ubisoft_gb = QtWidgets.QGroupBox(LegendarySettings)
self.ubisoft_gb.setObjectName("ubisoft_gb")
self.verticalLayout = QtWidgets.QVBoxLayout(self.ubisoft_gb)
self.verticalLayout.setObjectName("verticalLayout")
self.gridLayout.addWidget(self.ubisoft_gb, 1, 0, 1, 2)
self.left_layout = QtWidgets.QVBoxLayout()
self.left_layout.setObjectName("left_layout")
self.install_dir_group = QtWidgets.QGroupBox(LegendarySettings)
@ -96,41 +125,20 @@ class Ui_LegendarySettings(object):
self.disable_https_check.setObjectName("disable_https_check")
self.download_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.disable_https_check)
self.left_layout.addWidget(self.download_group)
self.gridLayout.addLayout(self.left_layout, 0, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.left_layout.addItem(spacerItem)
self.settings_layout.addLayout(self.left_layout)
self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setObjectName("right_layout")
self.locale_group = QtWidgets.QGroupBox(LegendarySettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.locale_group.sizePolicy().hasHeightForWidth())
self.locale_group.setSizePolicy(sizePolicy)
self.locale_group.setObjectName("locale_group")
self.locale_layout = QtWidgets.QVBoxLayout(self.locale_group)
self.locale_layout.setObjectName("locale_layout")
self.right_layout.addWidget(self.locale_group)
self.cleanup_group = QtWidgets.QGroupBox(LegendarySettings)
self.cleanup_group.setObjectName("cleanup_group")
self.cleanup_layout = QtWidgets.QVBoxLayout(self.cleanup_group)
self.cleanup_layout.setObjectName("cleanup_layout")
self.clean_keep_manifests_button = QtWidgets.QPushButton(self.cleanup_group)
self.clean_keep_manifests_button.setObjectName("clean_keep_manifests_button")
self.cleanup_layout.addWidget(self.clean_keep_manifests_button)
self.clean_button = QtWidgets.QPushButton(self.cleanup_group)
self.clean_button.setObjectName("clean_button")
self.cleanup_layout.addWidget(self.clean_button)
self.right_layout.addWidget(self.cleanup_group)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.right_layout.addItem(spacerItem1)
self.settings_layout.addLayout(self.right_layout)
self.gridLayout.addItem(spacerItem, 2, 0, 1, 2)
self.retranslateUi(LegendarySettings)
QtCore.QMetaObject.connectSlotsByName(LegendarySettings)
def retranslateUi(self, LegendarySettings):
_translate = QtCore.QCoreApplication.translate
self.locale_group.setTitle(_translate("LegendarySettings", "Locale"))
self.cleanup_group.setTitle(_translate("LegendarySettings", "Cleanup"))
self.clean_keep_manifests_button.setText(_translate("LegendarySettings", "Clean, but keep manifests"))
self.clean_button.setText(_translate("LegendarySettings", "Remove everything"))
self.ubisoft_gb.setTitle(_translate("LegendarySettings", "Link Ubisoft Games"))
self.install_dir_group.setTitle(_translate("LegendarySettings", "Default Installation Directory"))
self.download_group.setTitle(_translate("LegendarySettings", "Download Settings"))
self.max_workers_label.setText(_translate("LegendarySettings", "Max Workers"))
@ -141,10 +149,6 @@ class Ui_LegendarySettings(object):
self.preferred_cdn_label.setText(_translate("LegendarySettings", "Preferred CDN"))
self.preferred_cdn_line.setPlaceholderText(_translate("LegendarySettings", "Default"))
self.disable_https_label.setText(_translate("LegendarySettings", "Disable HTTPS"))
self.locale_group.setTitle(_translate("LegendarySettings", "Locale"))
self.cleanup_group.setTitle(_translate("LegendarySettings", "Cleanup"))
self.clean_keep_manifests_button.setText(_translate("LegendarySettings", "Clean, but keep manifests"))
self.clean_button.setText(_translate("LegendarySettings", "Remove everything"))
if __name__ == "__main__":

View file

@ -6,15 +6,64 @@
<rect>
<x>0</x>
<y>0</y>
<width>552</width>
<height>268</height>
<width>564</width>
<height>374</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">LegendarySettings</string>
</property>
<layout class="QHBoxLayout" name="settings_layout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<layout class="QVBoxLayout" name="right_layout">
<item>
<widget class="QGroupBox" name="locale_group">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Locale</string>
</property>
<layout class="QVBoxLayout" name="locale_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="cleanup_group">
<property name="title">
<string>Cleanup</string>
</property>
<layout class="QVBoxLayout" name="cleanup_layout">
<item>
<widget class="QPushButton" name="clean_keep_manifests_button">
<property name="text">
<string>Clean, but keep manifests</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clean_button">
<property name="text">
<string>Remove everything</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="ubisoft_gb">
<property name="title">
<string>Link Ubisoft Games</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="left_layout">
<item>
<widget class="QGroupBox" name="install_dir_group">
@ -160,74 +209,20 @@
</layout>
</widget>
</item>
<item>
<spacer name="left_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="right_layout">
<item>
<widget class="QGroupBox" name="locale_group">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Locale</string>
</property>
<layout class="QVBoxLayout" name="locale_layout"/>
</widget>
</item>
<item>
<widget class="QGroupBox" name="cleanup_group">
<property name="title">
<string>Cleanup</string>
</property>
<layout class="QVBoxLayout" name="cleanup_layout">
<item>
<widget class="QPushButton" name="clean_keep_manifests_button">
<property name="text">
<string>Clean, but keep manifests</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clean_button">
<property name="text">
<string>Remove everything</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="right_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
<item row="2" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>