Skip to content

Commit

Permalink
1.9.4 (413)
Browse files Browse the repository at this point in the history
  • Loading branch information
denis15yo committed Jan 9, 2025
1 parent 6002c16 commit 8288c7d
Show file tree
Hide file tree
Showing 25 changed files with 569 additions and 51 deletions.
27 changes: 8 additions & 19 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Nicegram/NGData/Sources/NGSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,17 @@ public func checkPremium(completion: @escaping (Bool) -> Void) {
}

public func isPremium() -> Bool {
#if DEBUG
return true
#else
if #available(iOS 13.0, *) {
return PremiumContainer.shared
.getPremiumStatusUseCase()
.hasPremiumOnDevice()
} else {
return false
}
#endif
}

public func usetrButton() -> [(Bool, [String])] {
Expand Down
38 changes: 38 additions & 0 deletions Nicegram/NGLab/Sources/RegDate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,44 @@ public func makeNiceRegDateStr(_ date: String) -> String {
}
}

public func getDaysFromRegDate(with id: Int64) -> Signal<Int?, NoError> {
if let dateString = getCachedRegDate(id) {
return .single(days(from: dateString))
} else {
return getRegDate(id)
.skipError()
|> map { dateString in
days(from: dateString)
}
}
}

private func days(from dateString: String, to: Date = Date()) -> Int? {
let monthDateFormatter = DateFormatter()
monthDateFormatter.dateFormat = "yyyy-MM"

let dayDateFormatter = DateFormatter()
dayDateFormatter.dateFormat = "yyyy-MM-dd"

var convertDateFormatter = DateFormatter()

var date: Date?
if let monthDate = monthDateFormatter.date(from: dateString) {
date = monthDate
} else if let dayDate = dayDateFormatter.date(from: dateString) {
date = dayDate
}

if let date {
let calendar = Calendar.current
let components = calendar.dateComponents([.day], from: date, to: to)
if let days = components.day {
return days
}
}

return nil
}

public func resetRegDateCache() -> Void {
UserDefaults.standard.removePersistentDomain(forName: "CachedRegDate")
Expand Down
19 changes: 19 additions & 0 deletions Nicegram/NGPersonality/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")

swift_library(
name = "NGPersonality",
module_name = "NGPersonality",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/TelegramCore:TelegramCore",
"//submodules/TelegramApi:TelegramApi",
"//submodules/AccountContext:AccountContext",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//Nicegram/NGPersonalityCore:NGPersonalityCore"
],
visibility = [
"//visibility:public",
],
)
35 changes: 35 additions & 0 deletions Nicegram/NGPersonality/Sources/CollectGhostScore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import TelegramApi
import TelegramCore
import AccountContext
import SwiftSignalKit
import Network
import MtProtoKit
import Postbox
import FeatPersonality

private let container = PersonalityContainer.shared
private let checkCollectStateUseCase = container.checkCollectStateUseCase()
private let checkPreferencesStateUseCase = container.checkPreferencesStateUseCase()
private let collectGhostScoreUseCase = container.collectGhostScoreUseCase()

public func collectGhostScore(
with context: AccountContext,
completion: @escaping () -> Void = {}
) {
guard checkCollectStateUseCase(with: .ghostScore(.empty)) else { return }
guard checkPreferencesStateUseCase(with: .ghostScore(.empty)) else { return }


_ = context.account.postbox.transaction { transaction -> ChatListTotalUnreadState in
transaction.getTotalUnreadState(groupId: .root)
}
.start { state in
let count = state.count(for: .filtered, in: .messages, with: .contact)

collectGhostScoreUseCase(
with: context.account.peerId.toInt64(),
count: count
)
completion()
}
}
115 changes: 115 additions & 0 deletions Nicegram/NGPersonality/Sources/CollectInfluencerScore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import TelegramApi
import TelegramCore
import AccountContext
import SwiftSignalKit
import Network
import MtProtoKit
import Postbox
import FeatPersonality

private let container = PersonalityContainer.shared
private let checkCollectStateUseCase = container.checkCollectStateUseCase()
private let checkPreferencesStateUseCase = container.checkPreferencesStateUseCase()
private let collectInfluencerScoreUseCase = container.collectInfluencerScoreUseCase()

public func collectInfluencerScore(
with context: AccountContext,
completion: @escaping () -> Void = {}
) {
guard checkCollectStateUseCase(with: .influencerScore(.empty)) else { return }
guard checkPreferencesStateUseCase(with: .influencerScore(.empty)) else { return }


_ = influencerScore(with: context)
.start(next: { result in
collectInfluencerScoreUseCase(
with: context.account.peerId.toInt64(),
channelsCount: result.1,
participantsCount: result.0
)
completion()
})
}

private func influencerScore(
with context: AccountContext
) -> Signal<(Int32, Int32), NoError> {
dialogs(with: context)
|> mapToSignal { dialogs -> Signal<[Api.messages.ChatFull?], NoError> in
switch dialogs {
case let .dialogs(_, _, chats, _):
return fullChannels(with: context, chats: chats)
case let .dialogsSlice(_, _, _, chats, _):
return fullChannels(with: context, chats: chats)
default: return .single([])
}
}
|> map { fullChannels -> (Int32, Int32) in
var count: Int32 = 0

fullChannels.forEach { chatFull in
switch chatFull {
case let .chatFull(fullChat, _, _):
switch fullChat {
case let .channelFull(_, _, _, _, participantsCount, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
count += (participantsCount ?? 0)
default: break
}
default: break
}
}

return (count, Int32(fullChannels.count))
}
}

private func fullChannels(
with context: AccountContext,
chats: [Api.Chat]
) -> Signal<[Api.messages.ChatFull?], NoError> {
combineLatest(
chats.compactMap { chat in
switch chat {
case let .channel(flags, _, id, accessHash, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
if (flags & Int32(1 << 0)) != 0 {
return fullChannel(with: context, channelId: id, accessHash: accessHash ?? 0)
} else {
return nil
}
default: return nil
}
}
)
}

private func fullChannel(
with context: AccountContext,
channelId: Int64,
accessHash: Int64
) -> Signal<Api.messages.ChatFull?, NoError> {
context.account.network.request(Api.functions.channels.getFullChannel(
channel: .inputChannel(channelId: channelId, accessHash: accessHash)
))
|> map(Optional.init)
|> `catch` { error -> Signal<Api.messages.ChatFull?, NoError> in
return .single(nil)
}
}

private func dialogs(
with context: AccountContext
) -> Signal<Api.messages.Dialogs?, NoError> {
context.account.network.request(Api.functions.messages.getDialogs(
flags: 0,
folderId: nil,
offsetDate: 0,
offsetId: 0,
offsetPeer: .inputPeerSelf,
limit: .max,
hash: 0
))
|> map(Optional.init)
|> `catch` { error -> Signal<Api.messages.Dialogs?, NoError> in
return .single(nil)
}
}
106 changes: 106 additions & 0 deletions Nicegram/NGPersonality/Sources/CollectMessagesActivity.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import TelegramApi
import TelegramCore
import AccountContext
import SwiftSignalKit
import Network
import MtProtoKit
import Postbox
import FeatPersonality

private let container = PersonalityContainer.shared
private let checkCollectStateUseCase = container.checkCollectStateUseCase()
private let checkPreferencesStateUseCase = container.checkPreferencesStateUseCase()
private let collectMessagesActivityUseCase = container.collectMessagesActivityUseCase()

public func collectMessagesActivity(
with context: AccountContext,
completion: @escaping () -> Void = {}
) {
guard checkCollectStateUseCase(with: .messagesActivity(.empty)) else { return }
guard checkPreferencesStateUseCase(with: .messagesActivity(.empty)) else { return }

_ = combineLatest(
searchGlobal(with: context),
search(with: context)
)
.start { all, user in
var allCount: Int32 = 0
var userCount: Int32 = 0

switch all {
case let .channelMessages(_, _, count, _, _, _, _, _):
allCount = count
case let .messagesSlice(_, count, _, _, _, _, _):
allCount = count
default: break
}
switch user {
case let .channelMessages(_, _, count, _, _, _, _, _):
userCount = count
case let .messagesSlice(_, count, _, _, _, _, _):
userCount = count
default: break
}

collectMessagesActivityUseCase(
with: context.account.peerId.toInt64(),
allMessagesCount: allCount,
userMessagesCount: userCount
)

completion()
}
}

// limit = 0, return only count without messages
func search(
with context: AccountContext,
peer: Api.InputPeer = .inputPeerEmpty,
from: Api.InputPeer = .inputPeerSelf,
limit: Int32 = 0
) -> Signal<Api.messages.Messages?, NoError> {
context.account.network.request(Api.functions.messages.search(
flags: 0,
peer: peer,
q: "",
fromId: from,
savedPeerId: nil,
savedReaction: nil,
topMsgId: nil,
filter: .inputMessagesFilterEmpty,
minDate: 0,
maxDate: 0,
offsetId: 0,
addOffset: 0,
limit: limit,
maxId: 0,
minId: 0,
hash: 0
))
|> map(Optional.init)
|> `catch` { error -> Signal<Api.messages.Messages?, NoError> in
return .single(nil)
}
}

private func searchGlobal(
with context: AccountContext,
limit: Int32 = 0
) -> Signal<Api.messages.Messages?, NoError> {
context.account.network.request(Api.functions.messages.searchGlobal(
flags: 0,
folderId: nil,
q: "",
filter: .inputMessagesFilterEmpty,
minDate: 0,
maxDate: 0,
offsetRate: 0,
offsetPeer: .inputPeerEmpty,
offsetId: 0,
limit: limit
))
|> map(Optional.init)
|> `catch` { error -> Signal<Api.messages.Messages?, NoError> in
return .single(nil)
}
}
Loading

0 comments on commit 8288c7d

Please sign in to comment.