loris/lib/business_logic/account/account.dart

317 lines
7.8 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:loris/business_logic/emoji/emoji.dart';
import 'package:loris/business_logic/timeline/timeline.dart';
import 'package:loris/global.dart' as global;
class AccountModel {
final String acct;
final String displayName;
final String avatar;
final String url;
final String id;
final String note;
final String header;
final bool locked;
final bool? discoverable;
final List<dynamic>? fields;
final bool? bot;
final bool? suspended;
final String identity;
final List<Emoji> emojis;
AccountModel({
required this.identity,
required this.note,
required this.header,
required this.locked,
this.discoverable,
this.fields,
this.bot,
this.suspended,
required this.acct,
required this.displayName,
required this.avatar,
required this.url,
required this.id,
required this.emojis,
});
factory AccountModel.fromJson(Map<String, dynamic> json, String identity) {
List<Emoji> emoji = [];
if (json["emojis"] != null) {
for (var e in json["emojis"]) {
emoji.add(Emoji.fromJson(e));
}
}
return AccountModel(
identity: identity,
id: json["id"],
acct: json["acct"],
displayName: json["display_name"],
avatar: json["avatar"],
url: json["url"],
note: json["note"],
discoverable: json["discoverable"],
header: json["header"],
locked: json["locked"],
bot: json["bot"],
fields: json["fields"],
suspended: json["suspended"],
emojis: emoji,
);
}
}
class RelationshipModel {
final String identity;
final bool blockedBy;
final bool blocking;
final bool endorsed;
final bool followedBy;
final bool following;
final String id;
final bool muting;
final bool mutingNotifications;
final String note;
final bool notifying;
final bool requested;
final bool showingReblogs;
RelationshipModel({
required this.identity,
required this.blockedBy,
required this.blocking,
required this.endorsed,
required this.followedBy,
required this.following,
required this.id,
required this.muting,
required this.mutingNotifications,
required this.note,
required this.notifying,
required this.requested,
required this.showingReblogs,
});
factory RelationshipModel.fromJson(
Map<String, dynamic> json,
String identity,
) {
return RelationshipModel(
identity: identity,
blockedBy: json["blocked_by"],
blocking: json["blocking"],
endorsed: json["endorsed"],
followedBy: json["followed_by"],
following: json["following"],
id: json["id"],
muting: json["muting"],
mutingNotifications: json["muting_notifications"],
note: json["note"],
notifying: json["notifying"],
requested: json["requested"],
showingReblogs: json["showing_reblogs"]);
}
}
Future<Map<int, RelationshipModel?>> getRelationship(
String identityName, String id) async {
final identity = global.settings!.identities[identityName]!;
Map<String, String> headers = identity.getAuthHeaders();
headers.addAll(global.defaultHeaders);
final uri = Uri(
scheme: "https",
host: identity.instanceUrl,
path: "/api/v1/accounts/relationships",
queryParameters: {"id": id},
);
final response = await http.get(uri, headers: headers);
if (response.statusCode == 200 && jsonDecode(response.body).isNotEmpty) {
return {
response.statusCode:
RelationshipModel.fromJson(jsonDecode(response.body)[0], identityName)
};
}
return {response.statusCode: null};
}
Future<Map<int, AccountModel?>> searchModel(
String identityName, String url) async {
final identity = global.settings!.identities[identityName]!;
Map<String, String> headers = identity.getAuthHeaders();
headers.addAll(global.defaultHeaders);
Map<String, String> params = {
"type": "accounts",
"q": url,
"limit": "1",
"resolve": "true",
};
final uri1 = Uri(
scheme: "https",
host: identity.instanceUrl,
path: "/api/v1/search",
queryParameters: params,
);
final uri2 = Uri(
scheme: "https",
host: identity.instanceUrl,
path: "/api/v2/search",
queryParameters: params,
);
final r1 = await http.get(uri1, headers: headers);
if (r1.statusCode == 200) {
List<dynamic> accounts = jsonDecode(r1.body)["accounts"];
if (accounts.isEmpty) {
return {r1.statusCode: null};
}
return {
r1.statusCode: AccountModel.fromJson(
jsonDecode(r1.body)["accounts"][0],
identityName,
)
};
}
final r2 = await http.get(uri2, headers: headers);
if (r2.statusCode == 200) {
List<dynamic> accounts = jsonDecode(r2.body)["accounts"];
if (accounts.isEmpty) {
return {r2.statusCode: null};
}
return {
r2.statusCode: AccountModel.fromJson(
jsonDecode(r2.body)["accounts"][0],
identityName,
)
};
}
return {r2.statusCode: null};
}
Future<MapEntry<int, List<ThreadModel>?>> getPostsForAccount(
AccountModel model,
String? maxid,
) async {
final identity = global.settings!.identities[model.identity];
var headers = identity!.getAuthHeaders();
headers.addAll(global.defaultHeaders);
final params = {
"limit": global.settings!.batchSize.toString(),
if (maxid != null) "max_id": maxid,
};
final uri = Uri(
scheme: "https",
host: identity.instanceUrl,
path: "/api/v1/accounts/${model.id}/statuses",
queryParameters: params,
);
final r = await http.get(uri, headers: headers);
if (r.statusCode != 200) {
return MapEntry(r.statusCode, null);
}
List<dynamic> rb = jsonDecode(r.body);
List<PostModel> posts = [];
for (var element in rb) {
posts.add(PostModel.fromJson(element, model.identity));
}
// posts.sort();
List<ThreadModel> threads = [];
for (var element in posts) {
threads.add(
await element.getThread(),
);
}
return MapEntry(r.statusCode, threads);
}
enum AccountInteractionTypes {
follow,
block,
mute,
}
extension AccountInteractionTypesExenstion on AccountInteractionTypes {
String get slug {
switch (this) {
case AccountInteractionTypes.block:
return "block";
case AccountInteractionTypes.follow:
return "follow";
case AccountInteractionTypes.mute:
return "mute";
}
}
IconData get icon {
switch (this) {
case AccountInteractionTypes.block:
return Icons.block;
case AccountInteractionTypes.follow:
return Icons.person_add;
case AccountInteractionTypes.mute:
return Icons.volume_off;
}
}
String get revokeSlug {
switch (this) {
case AccountInteractionTypes.block:
return "unblock";
case AccountInteractionTypes.follow:
return "unfollow";
case AccountInteractionTypes.mute:
return "unmute";
}
}
}
enum AccountTextInteractionTypes {
note,
report,
}
Future<MapEntry<int, RelationshipModel?>> performInteraction(
String identityName,
String accountId,
AccountInteractionTypes type,
bool revoke,
) async {
final identity = global.settings!.identities[identityName]!;
var headers = identity.getAuthHeaders();
headers.addAll(global.defaultHeaders);
headers.remove("Content-Type");
final uri = Uri(
scheme: "https",
host: identity.instanceUrl,
path:
"/api/v1/accounts/$accountId/${revoke ? type.revokeSlug : type.slug}");
final response = await http.post(uri, headers: headers);
if (response.statusCode != 200) {
return MapEntry(response.statusCode, null);
}
return MapEntry(
response.statusCode,
RelationshipModel.fromJson(
jsonDecode(response.body),
identityName,
),
);
}