You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RnQ/RnQ/history.pas

393 lines
9.9 KiB
Plaintext

{
This file is part of R&Q.
Under same license
}
unit history;
{$I RnQConfig.inc}
interface
uses
Windows, classes, events, sysutils, graphics,
RDGlobal, RnQDialogs, RnQProtocol, DateUtils;
{$I NoRTTI.inc}
const
CRYPT_SIMPLE = 0;
CRYPT_KEY1 = 1;
type
Thistory = class
private
huid: TUID;
loading: boolean;
cryptMode: byte;
hashed: RawByteString;
function old_fromStream(str: Tstream; uid: TUID): boolean;
public
themeToken, SmilesToken: Cardinal;
old_eventList: TList;
constructor Create(const uid: TUID);
destructor Destroy;
class function getExistingChats: TUIDS;
function getAllEvents: Thevents;
function getLastEvents(offset, cnt: Integer; var noMoreMessages: Boolean): Thevents;
function getLastEvent(cnt: integer = 1): Thevent;
function getTimeRange(fromTime, toTime: TDateTime; var noMoreMessages: Boolean; toInclusive: Boolean = True): Thevents; overload;
function getTimeRange(fromTime, toTime: TDateTime): Thevents; overload;
function getByRowID(rowID: Int64): Thevent;
function getByMsgID(pID: Int64): Thevent;
function getByTime(time: TDateTime): Thevent;
function getByWID(const wid: String): Thevent;
function getBySender(const sender: TUID): Thevents;
procedure writeWID(MsgID: Int64; const WID: RawByteString);
procedure deleteFromToTime(st, en: TDateTime);
procedure deleteBySender(const sender: TUID);
function dataSearch(const txt: String; caseSensitive: Boolean = False): Thevents;
function old_Load(cnt: TRnQContact): boolean;
end; // Thistory
procedure DelHistWith(const uid: TUID);
function ExistsHistWith(const uid: TUID): boolean;
procedure WriteToHistory(ev: Thevent; other: TRnQContact = nil);
implementation
uses
RDFileUtil, RnQBinUtils,
RQUtil, RnQLangs,
utilLib, globalLib, SQLiteDB;
function Thistory.old_Load(cnt: TRnQContact): Boolean;
{$IFNDEF DB_ENABLED}
var
str: Tstream;
memstream: TMemoryStream;
{$ENDIF ~DB_ENABLED}
begin
Result := False;
if not Assigned(cnt) then
Exit;
// Result := fromString(loadFile(userPath+historyPath + uid), quite);
str := GetStream(Account.ProtoPath + historyPath + cnt.UID2cmp);
if Assigned(str) then
begin
str.Position := 0;
// Result := fromSteam(str, quite);
memstream := TMemoryStream.Create;
memstream.CopyFrom(str, str.Size);
memstream.Position := 0;
FreeAndNil(str);
Result := old_fromStream(memstream, cnt.UID2cmp);
FreeAndNil(memstream);
end else
Result := old_fromStream(nil, cnt.UID2cmp);
end;
constructor Thistory.Create(const uid: TUID);
begin
huid := uid;
if uid = '' then
old_eventList := TList.Create
else
old_eventList := nil;
end;
destructor Thistory.Destroy;
begin
if Assigned(old_eventList) then
FreeAndNil(old_eventList);
end;
function SortFunc(Item1, Item2: Pointer): Integer;
begin
Result := CompareDateTime(Thevent(Item1).when, Thevent(Item2).when);
end;
function Thistory.old_fromStream(str: Tstream; uid: TUID): boolean;
var
ev: Thevent;
thisCnt, thisCnt2: TRnQContact;
Cnt1I, Cnt2I: Int64;
// cur:integer;
function getByte: byte;
begin
str.Read(Result, 1);
// inc(cur)
end;
function getDatetime: Tdatetime;
begin
str.Read(Result, 8);
// inc(cur,8)
end;
function getInt: integer;
begin
str.Read(Result, 4);
// inc(cur,4);
end;
function getString: RawByteString;
var
i: integer;
begin
i := getInt;
SetLength(Result, i);
str.Read(Result[1], i);
// inc(cur,length(result))
end;
procedure parseExtrainfo;
var
code, next, extraEnd: integer;
cur: integer;
s: AnsiString;
begin
cur := 1;
extraEnd := 4 + getInt;
inc(cur, 4);
while cur < extraEnd do
begin
code := getInt;
inc(cur, 4);
// inc(cur, 4);
next := cur + getInt + 4;
case code of
EI_flags:
begin
ev.flags := getInt;
// inc(cur, 4);
end;
EI_UID:
begin
// s := str.re
s := getString;
if Length(s) > 0 then
if Assigned(thisCnt) and thisCnt.equals(s) then
ev.who := thisCnt
else if Account.AccProto.getMyInfo.equals(s) then
ev.who := Account.AccProto.getMyInfo
else
begin
thisCnt := Account.AccProto.getContact(s);
ev.who := thisCnt;
end;
end;
EI_WID:
begin
ev.WID := getString;
end;
end;
cur := next;
end;
end; // parseExtraInfo
var
len: Int64;
// iu : TUID;
i: Integer;
curPos: Int64;
begin
loading := True;
try
// cur:=1;
cryptMode := CRYPT_SIMPLE;
hashed := '';
Cnt2I := 0;
Cnt1I := 0;
if not Assigned(str) then
begin
Result := True;
Exit;
end;
len := str.Size;
thisCnt := nil;
thisCnt2 := nil;
str.Seek(0, 0);
curPos := 0;
// while str.Position < len do
if len > 0 then
repeat
ev := Thevent.Create;
case getInt of
// case getInt1(str) of
HI_event:
begin
ev.cryptMode := cryptMode;
ev.kind := getByte;
begin
// iu := IntToStr(getInt);
i := getInt;
if i > 0 then
begin
if Assigned(thisCnt) and thisCnt.equals(i) then
begin
inc(Cnt1I);
ev.who := thisCnt
end
else if Account.AccProto.getMyInfo.equals(i) then
ev.who := Account.AccProto.getMyInfo
else if Assigned(thisCnt2) and thisCnt2.equals(i) then
begin
inc(Cnt2I);
ev.who := thisCnt2
end
else
begin
if not Assigned(thisCnt) or (Assigned(thisCnt2) and (Cnt2I > Cnt1I)) then
begin
Cnt1I := 0;
thisCnt := Account.AccProto.getContact(i);
ev.who := thisCnt;
end
else
begin
Cnt2I := 0;
thisCnt2 := Account.AccProto.getContact(i);
ev.who := thisCnt2;
end
end
end
else
begin
// thisCnt := NIL;
ev.who := Account.AccProto.getMyInfo;
end
end;
ev.when := getDatetime;
parseExtrainfo;
ev.old_decryptInfo(getString);
old_eventList.add(ev);
end;
HI_hashed:
hashed := getString;
HI_cryptMode:
begin
// getInt; // skip length
str.Seek(4, soFromCurrent); // skip length
cryptMode := getByte;
end;
else
begin
TThread.Queue(nil, procedure
begin
msgDlg(getTranslation('The history of %s is corrupted, some data is lost', [uid]), True, mtError);
end);
Result := False;
Exit;
end;
end;
curPos := str.Position;
until (curPos >= len);
Result := True;
finally
loading := false;
end;
end; // fromStream
class function Thistory.getExistingChats: TUIDS;
begin
Result := SQLHist.GetExistingChats;
end;
function Thistory.getAllEvents: Thevents;
begin
Result := SQLHist.GetAll(huid);
end;
function Thistory.getLastEvents(offset, cnt: Integer; var noMoreMessages: Boolean): Thevents;
begin
Result := SQLHist.GetLastMulti(huid, offset, cnt, noMoreMessages);
end;
function Thistory.getLastEvent(cnt: integer = 1): Thevent;
begin
Result := SQLHist.GetLastSingle(huid, cnt);
end;
function Thistory.getTimeRange(fromTime, toTime: TDateTime; var noMoreMessages: Boolean; toInclusive: Boolean = True): Thevents;
begin
Result := SQLHist.GetByTimeRange(huid, fromTime, toTime, noMoreMessages, toInclusive);
end;
function Thistory.getTimeRange(fromTime, toTime: TDateTime): Thevents;
var
dummy: Boolean;
begin
Result := SQLHist.GetByTimeRange(huid, fromTime, toTime, dummy);
end;
function Thistory.getByRowID(rowID: Int64): Thevent;
begin
Result := SQLHist.GetByRowID(huid, rowID);
end;
function Thistory.getByMsgID(pID: Int64): Thevent;
begin
Result := SQLHist.GetByMsgID(huid, pID);
end;
function Thistory.getByTime(time: TDateTime): Thevent;
begin
Result := SQLHist.GetByTime(huid, time);
end;
function Thistory.getByWID(const wid: String): Thevent;
begin
Result := SQLHist.GetByWID(huid, wid);
end;
function Thistory.getBySender(const sender: TUID): Thevents;
begin
Result := SQLHist.GetBySender(huid, sender);
end;
procedure Thistory.writeWID(MsgID: Int64; const WID: RawByteString);
begin
SQLHist.WriteWID(huid, MsgID, WID);
end;
procedure Thistory.deleteFromToTime(st, en: TDateTime);
begin
SQLHist.DeleteByTimeRange(huid, st, en);
end;
procedure Thistory.deleteBySender(const sender: TUID);
begin
SQLHist.DeleteBySender(huid, sender);
end;
function Thistory.dataSearch(const txt: String; caseSensitive: Boolean = False): Thevents;
begin
Result := SQLHist.DataSearch(huid, txt, caseSensitive);
end;
procedure DelHistWith(const uid: TUID);
begin
SQLHist.DeleteChat(uid);
end;
procedure WriteToHistory(ev: Thevent; other: TRnQContact = nil);
begin
ev := ev.clone;
if other <> nil then
ev.otherpeer := other;
if ev.otherpeer = nil then
ev.otherpeer := ev.chat;
if ev.otherpeer = nil then
ev.otherpeer := ev.who;
ev.WriteToHistory(ev.otherpeer.uid);
ev.Free;
end;
function ExistsHistWith(const uid: TUID): boolean;
begin
Result := SQLHist.ChatExists(uid);
end;
end.