feat(GODT-3121): added gRPC call and event for KB suggestions.

This commit is contained in:
Xavier Michelon 2023-11-27 18:59:37 +01:00
parent 51722eb1a4
commit 3070912416
12 changed files with 1372 additions and 1068 deletions

View File

@ -22,6 +22,7 @@ import (
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/ProtonMail/proton-bridge/v3/internal/kb"
"github.com/ProtonMail/proton-bridge/v3/internal/safe"
"github.com/ProtonMail/proton-bridge/v3/internal/services/userevents"
"github.com/ProtonMail/proton-bridge/v3/internal/updater"
@ -310,6 +311,10 @@ func (bridge *Bridge) SetColorScheme(colorScheme string) error {
return bridge.vault.SetColorScheme(colorScheme)
}
func (bridge *Bridge) GetKnowledgeBaseSuggestions(userInput string) (kb.ArticleList, error) {
return kb.GetSuggestions(userInput)
}
// FactoryReset deletes all users, wipes the vault, and deletes all files.
// Note: it does not clear the keychain. The only entry in the keychain is the vault password,
// which we need at next startup to decrypt the vault.

View File

@ -568,6 +568,14 @@ grpc::Status GRPCClient::hostname(QString &outHostname) {
}
//****************************************************************************************************************************************************
/// \param[in] input The user input to analyze.
//****************************************************************************************************************************************************
grpc::Status GRPCClient::RequestKnowledgeBaseSuggestions(QString const &input) {
return this->logGRPCCallStatus(this->setString(&Bridge::Stub::RequestKnowledgeBaseSuggestions, input), __FUNCTION__);
}
//****************************************************************************************************************************************************
/// \param[out] outPath The value for the property.
/// \return The status for the gRPC call.
@ -1164,6 +1172,19 @@ void GRPCClient::processAppEvent(AppEvent const &event) {
this->logTrace("App event received: CertificateInstallFailed.");
emit certificateInstallFailed();
break;
case AppEvent::kKnowledgeBaseSuggestions:
{
this->logTrace("App event received: KnowledgeBaseSuggestions.");
QList<KnowledgeBaseSuggestion> suggestions;
for (grpc::KnowledgeBaseSuggestion const &suggestion: event.knowledgebasesuggestions().suggestions()) {
suggestions.push_back(KnowledgeBaseSuggestion{
.url = QString::fromUtf8(suggestion.url()),
.title = QString::fromUtf8(suggestion.title())
});
}
emit knowledgeBasSuggestions(suggestions);
break;
}
default:
this->logError("Unknown App event received.");
}

View File

@ -42,6 +42,15 @@ typedef grpc::Status (grpc::Bridge::Stub::*StringParamMethod)(grpc::ClientContex
typedef std::unique_ptr<grpc::ClientContext> UPClientContext;
//****************************************************************************************************************************************************
/// \brief A struct for knowledge base suggestion.
//****************************************************************************************************************************************************
struct KnowledgeBaseSuggestion {
QString url; ///< The URL of the knowledge base article
QString title; ///< The title of the knowledge base article.
};
//****************************************************************************************************************************************************
/// \brief gRPC client class. This class encapsulate the gRPC service, abstracting all data type conversions.
//****************************************************************************************************************************************************
@ -93,6 +102,7 @@ public: // member functions.
grpc::Status releaseNotesPageLink(QUrl &outUrl); ///< Performs the 'releaseNotesPageLink' call.
grpc::Status landingPageLink(QUrl &outUrl); ///< Performs the 'landingPageLink' call.
grpc::Status hostname(QString &outHostname); ///< Performs the 'Hostname' call.
grpc::Status RequestKnowledgeBaseSuggestions(QString const &input); ///< Performs the 'RequestKnowledgeBaseSuggestions' call.
signals: // app related signals
void internetStatus(bool isOn);
@ -106,9 +116,10 @@ signals: // app related signals
void certificateInstallCanceled();
void certificateInstallFailed();
void showMainWindow();
void knowledgeBasSuggestions(QList<KnowledgeBaseSuggestion> const& suggestions);
// cache related calls
public:
public: // cache related calls
grpc::Status diskCachePath(QUrl &outPath); ///< Performs the 'diskCachePath' call.
grpc::Status setDiskCachePath(QUrl const &path); ///< Performs the 'setDiskCachePath' call
@ -117,8 +128,8 @@ signals:
void diskCachePathChanged(QUrl const &path);
void diskCachePathChangeFinished();
// mail settings related calls
public:
public: // mail settings related calls
grpc::Status mailServerSettings(qint32 &outIMAPPort, qint32 &outSMTPPort, bool &outUseSSLForIMAP, bool &outUseSSLForSMTP); ///< Performs the 'MailServerSettings' gRPC call.
grpc::Status setMailServerSettings(qint32 imapPort, qint32 smtpPort, bool useSSLForIMAP, bool useSSLForSMTP); ///< Performs the 'SetMailServerSettings' gRPC call.
grpc::Status isDoHEnabled(bool &outEnabled); ///< Performs the 'isDoHEnabled' gRPC call.

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,7 @@ service Bridge {
rpc ReportBug(ReportBugRequest) returns (google.protobuf.Empty);
rpc ForceLauncher(google.protobuf.StringValue) returns (google.protobuf.Empty);
rpc SetMainExecutable(google.protobuf.StringValue) returns (google.protobuf.Empty);
rpc RequestKnowledgeBaseSuggestions(google.protobuf.StringValue) returns (google.protobuf.Empty);
// login
rpc Login(LoginRequest) returns (google.protobuf.Empty);
@ -269,6 +270,7 @@ message AppEvent {
CertificateInstallSuccessEvent certificateInstallSuccess = 9;
CertificateInstallCanceledEvent certificateInstallCanceled = 10;
CertificateInstallFailedEvent certificateInstallFailed = 11;
KnowledgeBaseSuggestionsEvent knowledgeBaseSuggestions = 12;
}
}
@ -287,6 +289,15 @@ message CertificateInstallSuccessEvent {}
message CertificateInstallCanceledEvent {}
message CertificateInstallFailedEvent {}
message KnowledgeBaseSuggestion {
string url = 1;
string title = 2;
}
message KnowledgeBaseSuggestionsEvent {
repeated KnowledgeBaseSuggestion suggestions = 1;
}
//**********************************************************
// Login related events
//**********************************************************
@ -478,6 +489,7 @@ message UserEvent {
}
}
message ToggleSplitModeFinishedEvent {
string userID = 1;
}

View File

@ -38,68 +38,69 @@ import (
const _ = grpc.SupportPackageIsVersion7
const (
Bridge_CheckTokens_FullMethodName = "/grpc.Bridge/CheckTokens"
Bridge_AddLogEntry_FullMethodName = "/grpc.Bridge/AddLogEntry"
Bridge_GuiReady_FullMethodName = "/grpc.Bridge/GuiReady"
Bridge_Quit_FullMethodName = "/grpc.Bridge/Quit"
Bridge_Restart_FullMethodName = "/grpc.Bridge/Restart"
Bridge_ShowOnStartup_FullMethodName = "/grpc.Bridge/ShowOnStartup"
Bridge_SetIsAutostartOn_FullMethodName = "/grpc.Bridge/SetIsAutostartOn"
Bridge_IsAutostartOn_FullMethodName = "/grpc.Bridge/IsAutostartOn"
Bridge_SetIsBetaEnabled_FullMethodName = "/grpc.Bridge/SetIsBetaEnabled"
Bridge_IsBetaEnabled_FullMethodName = "/grpc.Bridge/IsBetaEnabled"
Bridge_SetIsAllMailVisible_FullMethodName = "/grpc.Bridge/SetIsAllMailVisible"
Bridge_IsAllMailVisible_FullMethodName = "/grpc.Bridge/IsAllMailVisible"
Bridge_SetIsTelemetryDisabled_FullMethodName = "/grpc.Bridge/SetIsTelemetryDisabled"
Bridge_IsTelemetryDisabled_FullMethodName = "/grpc.Bridge/IsTelemetryDisabled"
Bridge_GoOs_FullMethodName = "/grpc.Bridge/GoOs"
Bridge_TriggerReset_FullMethodName = "/grpc.Bridge/TriggerReset"
Bridge_Version_FullMethodName = "/grpc.Bridge/Version"
Bridge_LogsPath_FullMethodName = "/grpc.Bridge/LogsPath"
Bridge_LicensePath_FullMethodName = "/grpc.Bridge/LicensePath"
Bridge_ReleaseNotesPageLink_FullMethodName = "/grpc.Bridge/ReleaseNotesPageLink"
Bridge_DependencyLicensesLink_FullMethodName = "/grpc.Bridge/DependencyLicensesLink"
Bridge_LandingPageLink_FullMethodName = "/grpc.Bridge/LandingPageLink"
Bridge_SetColorSchemeName_FullMethodName = "/grpc.Bridge/SetColorSchemeName"
Bridge_ColorSchemeName_FullMethodName = "/grpc.Bridge/ColorSchemeName"
Bridge_CurrentEmailClient_FullMethodName = "/grpc.Bridge/CurrentEmailClient"
Bridge_ReportBug_FullMethodName = "/grpc.Bridge/ReportBug"
Bridge_ForceLauncher_FullMethodName = "/grpc.Bridge/ForceLauncher"
Bridge_SetMainExecutable_FullMethodName = "/grpc.Bridge/SetMainExecutable"
Bridge_Login_FullMethodName = "/grpc.Bridge/Login"
Bridge_Login2FA_FullMethodName = "/grpc.Bridge/Login2FA"
Bridge_Login2Passwords_FullMethodName = "/grpc.Bridge/Login2Passwords"
Bridge_LoginAbort_FullMethodName = "/grpc.Bridge/LoginAbort"
Bridge_CheckUpdate_FullMethodName = "/grpc.Bridge/CheckUpdate"
Bridge_InstallUpdate_FullMethodName = "/grpc.Bridge/InstallUpdate"
Bridge_SetIsAutomaticUpdateOn_FullMethodName = "/grpc.Bridge/SetIsAutomaticUpdateOn"
Bridge_IsAutomaticUpdateOn_FullMethodName = "/grpc.Bridge/IsAutomaticUpdateOn"
Bridge_DiskCachePath_FullMethodName = "/grpc.Bridge/DiskCachePath"
Bridge_SetDiskCachePath_FullMethodName = "/grpc.Bridge/SetDiskCachePath"
Bridge_SetIsDoHEnabled_FullMethodName = "/grpc.Bridge/SetIsDoHEnabled"
Bridge_IsDoHEnabled_FullMethodName = "/grpc.Bridge/IsDoHEnabled"
Bridge_MailServerSettings_FullMethodName = "/grpc.Bridge/MailServerSettings"
Bridge_SetMailServerSettings_FullMethodName = "/grpc.Bridge/SetMailServerSettings"
Bridge_Hostname_FullMethodName = "/grpc.Bridge/Hostname"
Bridge_IsPortFree_FullMethodName = "/grpc.Bridge/IsPortFree"
Bridge_AvailableKeychains_FullMethodName = "/grpc.Bridge/AvailableKeychains"
Bridge_SetCurrentKeychain_FullMethodName = "/grpc.Bridge/SetCurrentKeychain"
Bridge_CurrentKeychain_FullMethodName = "/grpc.Bridge/CurrentKeychain"
Bridge_GetUserList_FullMethodName = "/grpc.Bridge/GetUserList"
Bridge_GetUser_FullMethodName = "/grpc.Bridge/GetUser"
Bridge_SetUserSplitMode_FullMethodName = "/grpc.Bridge/SetUserSplitMode"
Bridge_SendBadEventUserFeedback_FullMethodName = "/grpc.Bridge/SendBadEventUserFeedback"
Bridge_LogoutUser_FullMethodName = "/grpc.Bridge/LogoutUser"
Bridge_RemoveUser_FullMethodName = "/grpc.Bridge/RemoveUser"
Bridge_ConfigureUserAppleMail_FullMethodName = "/grpc.Bridge/ConfigureUserAppleMail"
Bridge_ReportBugClicked_FullMethodName = "/grpc.Bridge/ReportBugClicked"
Bridge_AutoconfigClicked_FullMethodName = "/grpc.Bridge/AutoconfigClicked"
Bridge_ExternalLinkClicked_FullMethodName = "/grpc.Bridge/ExternalLinkClicked"
Bridge_IsTLSCertificateInstalled_FullMethodName = "/grpc.Bridge/IsTLSCertificateInstalled"
Bridge_InstallTLSCertificate_FullMethodName = "/grpc.Bridge/InstallTLSCertificate"
Bridge_ExportTLSCertificates_FullMethodName = "/grpc.Bridge/ExportTLSCertificates"
Bridge_RunEventStream_FullMethodName = "/grpc.Bridge/RunEventStream"
Bridge_StopEventStream_FullMethodName = "/grpc.Bridge/StopEventStream"
Bridge_CheckTokens_FullMethodName = "/grpc.Bridge/CheckTokens"
Bridge_AddLogEntry_FullMethodName = "/grpc.Bridge/AddLogEntry"
Bridge_GuiReady_FullMethodName = "/grpc.Bridge/GuiReady"
Bridge_Quit_FullMethodName = "/grpc.Bridge/Quit"
Bridge_Restart_FullMethodName = "/grpc.Bridge/Restart"
Bridge_ShowOnStartup_FullMethodName = "/grpc.Bridge/ShowOnStartup"
Bridge_SetIsAutostartOn_FullMethodName = "/grpc.Bridge/SetIsAutostartOn"
Bridge_IsAutostartOn_FullMethodName = "/grpc.Bridge/IsAutostartOn"
Bridge_SetIsBetaEnabled_FullMethodName = "/grpc.Bridge/SetIsBetaEnabled"
Bridge_IsBetaEnabled_FullMethodName = "/grpc.Bridge/IsBetaEnabled"
Bridge_SetIsAllMailVisible_FullMethodName = "/grpc.Bridge/SetIsAllMailVisible"
Bridge_IsAllMailVisible_FullMethodName = "/grpc.Bridge/IsAllMailVisible"
Bridge_SetIsTelemetryDisabled_FullMethodName = "/grpc.Bridge/SetIsTelemetryDisabled"
Bridge_IsTelemetryDisabled_FullMethodName = "/grpc.Bridge/IsTelemetryDisabled"
Bridge_GoOs_FullMethodName = "/grpc.Bridge/GoOs"
Bridge_TriggerReset_FullMethodName = "/grpc.Bridge/TriggerReset"
Bridge_Version_FullMethodName = "/grpc.Bridge/Version"
Bridge_LogsPath_FullMethodName = "/grpc.Bridge/LogsPath"
Bridge_LicensePath_FullMethodName = "/grpc.Bridge/LicensePath"
Bridge_ReleaseNotesPageLink_FullMethodName = "/grpc.Bridge/ReleaseNotesPageLink"
Bridge_DependencyLicensesLink_FullMethodName = "/grpc.Bridge/DependencyLicensesLink"
Bridge_LandingPageLink_FullMethodName = "/grpc.Bridge/LandingPageLink"
Bridge_SetColorSchemeName_FullMethodName = "/grpc.Bridge/SetColorSchemeName"
Bridge_ColorSchemeName_FullMethodName = "/grpc.Bridge/ColorSchemeName"
Bridge_CurrentEmailClient_FullMethodName = "/grpc.Bridge/CurrentEmailClient"
Bridge_ReportBug_FullMethodName = "/grpc.Bridge/ReportBug"
Bridge_ForceLauncher_FullMethodName = "/grpc.Bridge/ForceLauncher"
Bridge_SetMainExecutable_FullMethodName = "/grpc.Bridge/SetMainExecutable"
Bridge_RequestKnowledgeBaseSuggestions_FullMethodName = "/grpc.Bridge/RequestKnowledgeBaseSuggestions"
Bridge_Login_FullMethodName = "/grpc.Bridge/Login"
Bridge_Login2FA_FullMethodName = "/grpc.Bridge/Login2FA"
Bridge_Login2Passwords_FullMethodName = "/grpc.Bridge/Login2Passwords"
Bridge_LoginAbort_FullMethodName = "/grpc.Bridge/LoginAbort"
Bridge_CheckUpdate_FullMethodName = "/grpc.Bridge/CheckUpdate"
Bridge_InstallUpdate_FullMethodName = "/grpc.Bridge/InstallUpdate"
Bridge_SetIsAutomaticUpdateOn_FullMethodName = "/grpc.Bridge/SetIsAutomaticUpdateOn"
Bridge_IsAutomaticUpdateOn_FullMethodName = "/grpc.Bridge/IsAutomaticUpdateOn"
Bridge_DiskCachePath_FullMethodName = "/grpc.Bridge/DiskCachePath"
Bridge_SetDiskCachePath_FullMethodName = "/grpc.Bridge/SetDiskCachePath"
Bridge_SetIsDoHEnabled_FullMethodName = "/grpc.Bridge/SetIsDoHEnabled"
Bridge_IsDoHEnabled_FullMethodName = "/grpc.Bridge/IsDoHEnabled"
Bridge_MailServerSettings_FullMethodName = "/grpc.Bridge/MailServerSettings"
Bridge_SetMailServerSettings_FullMethodName = "/grpc.Bridge/SetMailServerSettings"
Bridge_Hostname_FullMethodName = "/grpc.Bridge/Hostname"
Bridge_IsPortFree_FullMethodName = "/grpc.Bridge/IsPortFree"
Bridge_AvailableKeychains_FullMethodName = "/grpc.Bridge/AvailableKeychains"
Bridge_SetCurrentKeychain_FullMethodName = "/grpc.Bridge/SetCurrentKeychain"
Bridge_CurrentKeychain_FullMethodName = "/grpc.Bridge/CurrentKeychain"
Bridge_GetUserList_FullMethodName = "/grpc.Bridge/GetUserList"
Bridge_GetUser_FullMethodName = "/grpc.Bridge/GetUser"
Bridge_SetUserSplitMode_FullMethodName = "/grpc.Bridge/SetUserSplitMode"
Bridge_SendBadEventUserFeedback_FullMethodName = "/grpc.Bridge/SendBadEventUserFeedback"
Bridge_LogoutUser_FullMethodName = "/grpc.Bridge/LogoutUser"
Bridge_RemoveUser_FullMethodName = "/grpc.Bridge/RemoveUser"
Bridge_ConfigureUserAppleMail_FullMethodName = "/grpc.Bridge/ConfigureUserAppleMail"
Bridge_ReportBugClicked_FullMethodName = "/grpc.Bridge/ReportBugClicked"
Bridge_AutoconfigClicked_FullMethodName = "/grpc.Bridge/AutoconfigClicked"
Bridge_ExternalLinkClicked_FullMethodName = "/grpc.Bridge/ExternalLinkClicked"
Bridge_IsTLSCertificateInstalled_FullMethodName = "/grpc.Bridge/IsTLSCertificateInstalled"
Bridge_InstallTLSCertificate_FullMethodName = "/grpc.Bridge/InstallTLSCertificate"
Bridge_ExportTLSCertificates_FullMethodName = "/grpc.Bridge/ExportTLSCertificates"
Bridge_RunEventStream_FullMethodName = "/grpc.Bridge/RunEventStream"
Bridge_StopEventStream_FullMethodName = "/grpc.Bridge/StopEventStream"
)
// BridgeClient is the client API for Bridge service.
@ -135,6 +136,7 @@ type BridgeClient interface {
ReportBug(ctx context.Context, in *ReportBugRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
ForceLauncher(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error)
SetMainExecutable(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error)
RequestKnowledgeBaseSuggestions(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error)
// login
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
Login2FA(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
@ -440,6 +442,15 @@ func (c *bridgeClient) SetMainExecutable(ctx context.Context, in *wrapperspb.Str
return out, nil
}
func (c *bridgeClient) RequestKnowledgeBaseSuggestions(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, Bridge_RequestKnowledgeBaseSuggestions_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bridgeClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, Bridge_Login_FullMethodName, in, out, opts...)
@ -802,6 +813,7 @@ type BridgeServer interface {
ReportBug(context.Context, *ReportBugRequest) (*emptypb.Empty, error)
ForceLauncher(context.Context, *wrapperspb.StringValue) (*emptypb.Empty, error)
SetMainExecutable(context.Context, *wrapperspb.StringValue) (*emptypb.Empty, error)
RequestKnowledgeBaseSuggestions(context.Context, *wrapperspb.StringValue) (*emptypb.Empty, error)
// login
Login(context.Context, *LoginRequest) (*emptypb.Empty, error)
Login2FA(context.Context, *LoginRequest) (*emptypb.Empty, error)
@ -936,6 +948,9 @@ func (UnimplementedBridgeServer) ForceLauncher(context.Context, *wrapperspb.Stri
func (UnimplementedBridgeServer) SetMainExecutable(context.Context, *wrapperspb.StringValue) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method SetMainExecutable not implemented")
}
func (UnimplementedBridgeServer) RequestKnowledgeBaseSuggestions(context.Context, *wrapperspb.StringValue) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method RequestKnowledgeBaseSuggestions not implemented")
}
func (UnimplementedBridgeServer) Login(context.Context, *LoginRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
}
@ -1555,6 +1570,24 @@ func _Bridge_SetMainExecutable_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _Bridge_RequestKnowledgeBaseSuggestions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(wrapperspb.StringValue)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BridgeServer).RequestKnowledgeBaseSuggestions(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Bridge_RequestKnowledgeBaseSuggestions_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BridgeServer).RequestKnowledgeBaseSuggestions(ctx, req.(*wrapperspb.StringValue))
}
return interceptor(ctx, in, info, handler)
}
func _Bridge_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LoginRequest)
if err := dec(in); err != nil {
@ -2289,6 +2322,10 @@ var Bridge_ServiceDesc = grpc.ServiceDesc{
MethodName: "SetMainExecutable",
Handler: _Bridge_SetMainExecutable_Handler,
},
{
MethodName: "RequestKnowledgeBaseSuggestions",
Handler: _Bridge_RequestKnowledgeBaseSuggestions_Handler,
},
{
MethodName: "Login",
Handler: _Bridge_Login_Handler,

View File

@ -17,6 +17,11 @@
package grpc
import (
"github.com/ProtonMail/proton-bridge/v3/internal/kb"
"github.com/bradenaw/juniper/xslices"
)
func NewInternetStatusEvent(connected bool) *StreamEvent {
return appEvent(&AppEvent{Event: &AppEvent_InternetStatus{InternetStatus: &InternetStatusEvent{Connected: connected}}})
}
@ -61,6 +66,20 @@ func NewShowMainWindowEvent() *StreamEvent {
return appEvent(&AppEvent{Event: &AppEvent_ShowMainWindow{ShowMainWindow: &ShowMainWindowEvent{}}})
}
func NewRequestKnowledgeBaseSuggestionsEvent(suggestions kb.ArticleList) *StreamEvent {
s := xslices.Map(
suggestions,
func(article kb.Article) *KnowledgeBaseSuggestion {
return &KnowledgeBaseSuggestion{Url: article.URL, Title: article.Title}
},
)
return appEvent(&AppEvent{Event: &AppEvent_KnowledgeBaseSuggestions{
KnowledgeBaseSuggestions: &KnowledgeBaseSuggestionsEvent{
Suggestions: s,
},
}})
}
func NewLoginError(err LoginErrorType, message string) *StreamEvent {
return loginEvent(&LoginEvent{Event: &LoginEvent_Error{Error: &LoginErrorEvent{Type: err, Message: message}}})
}

View File

@ -30,6 +30,7 @@ import (
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/ProtonMail/proton-bridge/v3/internal/frontend/theme"
"github.com/ProtonMail/proton-bridge/v3/internal/kb"
"github.com/ProtonMail/proton-bridge/v3/internal/safe"
"github.com/ProtonMail/proton-bridge/v3/internal/service"
"github.com/ProtonMail/proton-bridge/v3/internal/updater"
@ -375,6 +376,23 @@ func (s *Service) SetMainExecutable(_ context.Context, exe *wrapperspb.StringVal
return &emptypb.Empty{}, nil
}
func (s *Service) RequestKnowledgeBaseSuggestions(_ context.Context, userInput *wrapperspb.StringValue) (*emptypb.Empty, error) {
s.log.Debug("RequestKnowledgeBaseSuggestions")
go func() {
defer async.HandlePanic(s.panicHandler)
articles, err := s.bridge.GetKnowledgeBaseSuggestions(userInput.Value)
if err != nil {
s.log.WithError(err).Error("Could not retrieve KB article suggestions")
articles = kb.ArticleList{}
}
_ = s.SendEvent(NewRequestKnowledgeBaseSuggestionsEvent(articles))
}()
return &emptypb.Empty{}, nil
}
func (s *Service) Login(_ context.Context, login *LoginRequest) (*emptypb.Empty, error) {
s.log.WithField("username", login.Username).Debug("Login")

View File

@ -21,6 +21,7 @@ import (
"context"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/proton-bridge/v3/internal/kb"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
@ -122,6 +123,7 @@ func (s *Service) StartEventTest() error {
NewReportBugSuccessEvent(),
NewReportBugErrorEvent(),
NewShowMainWindowEvent(),
NewRequestKnowledgeBaseSuggestionsEvent(kb.ArticleList{}),
// login
NewLoginError(LoginErrorType_FREE_USER, "error"),

View File

@ -15,7 +15,7 @@
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
package knowledgebase
package kb
import (
_ "embed"
@ -44,6 +44,16 @@ func getArticleList() (ArticleList, error) {
// GetSuggestions return a list of up to 3 suggestions for KB articles matching the given user input.
func GetSuggestions(_ string) (ArticleList, error) {
// TBD
return ArticleList{}, nil
articles, err := getArticleList()
if err != nil {
return ArticleList{}, err
}
// note starting with go 1.21, we will be able to do:
// return articles[:min(3, len(articles))]
l := len(articles)
if l > 3 {
l = 3
}
return articles[:l], nil
}

View File

@ -15,7 +15,7 @@
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
package knowledgebase
package kb
import (
"testing"