Skip to content

Commit

Permalink
Add realtimeStatus
Browse files Browse the repository at this point in the history
  • Loading branch information
tsutsu3 committed Dec 8, 2024
1 parent d0537d0 commit 3b89474
Show file tree
Hide file tree
Showing 14 changed files with 7,055 additions and 98 deletions.
101 changes: 91 additions & 10 deletions lib/gateways/v6/api_gateway_v6.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart';
import 'package:http/http.dart' as http;
import 'package:pi_hole_client/functions/convert.dart';
import 'package:pi_hole_client/models/api/v6/auth/auth.dart';
import 'package:pi_hole_client/models/api/v6/dns/dns.dart';
// import 'package:pi_hole_client/functions/convert.dart';
import 'package:pi_hole_client/models/api/v6/auth/auth.dart' as v6;
import 'package:pi_hole_client/models/api/v6/dns/dns.dart' as v6;
import 'package:pi_hole_client/models/api/v6/flt/ftl.dart' as v6;
import 'package:pi_hole_client/models/api/v6/metrics/stats.dart' as v6;
import 'package:pi_hole_client/models/app_log.dart';
import 'package:pi_hole_client/models/domain.dart';
import 'package:pi_hole_client/functions/encode_basic_auth.dart';
// import 'package:pi_hole_client/functions/encode_basic_auth.dart';
import 'package:pi_hole_client/models/gateways.dart';
import 'package:pi_hole_client/models/log.dart';
import 'package:pi_hole_client/models/overtime_data.dart';
// import 'package:pi_hole_client/models/log.dart';
// import 'package:pi_hole_client/models/overtime_data.dart';
import 'package:pi_hole_client/models/realtime_status.dart';
import 'package:pi_hole_client/models/server.dart';
import 'package:pi_hole_client/gateways/api_gateway_interface.dart';
import 'package:pi_hole_client/functions/logger.dart';
// import 'package:pi_hole_client/functions/logger.dart';

class ApiGatewayV6 implements ApiGateway {
final Server server;
Expand Down Expand Up @@ -145,15 +147,15 @@ class ApiGatewayV6 implements ApiGateway {

// Login
if (status.statusCode == 200) {
final statusParsed = Session.fromJson(jsonDecode(status.body));
final statusParsed = v6.Session.fromJson(jsonDecode(status.body));
sid = statusParsed.session.sid;

// Get DNS blocking status
final enableOrDisable = await httpClient(
method: 'get', url: '${server.address}/api/dns/blocking');
if (enableOrDisable.statusCode == 200) {
final enableOrDisableParsed =
Blocking.fromJson(jsonDecode(enableOrDisable.body));
v6.Blocking.fromJson(jsonDecode(enableOrDisable.body));
return LoginQueryResponse(
result: APiResponseType.success,
status: enableOrDisableParsed.blocking,
Expand Down Expand Up @@ -231,7 +233,86 @@ class ApiGatewayV6 implements ApiGateway {
/// data in a structured format.
@override
Future<RealtimeStatusResponse> realtimeStatus() async {
throw UnimplementedError();
try {
final response = await Future.wait([
httpClient(
method: 'get',
url: '${server.address}/api/stats/summary',
),
httpClient(
method: 'get',
url: '${server.address}/api/info/ftl',
),
httpClient(
method: 'get',
url: '${server.address}/api/dns/blocking',
),
httpClient(
method: 'get',
url: '${server.address}/api/stats/top_domains',
),
httpClient(
method: 'get',
url: '${server.address}/api/stats/top_domains?blocked=true',
),
httpClient(
method: 'get',
url: '${server.address}/api/stats/top_clients',
),
httpClient(
method: 'get',
url: '${server.address}/api/stats/top_clients?blocked=true',
),
httpClient(
method: 'get',
url: '${server.address}/api/stats/upstreams',
),
]);
if (response[0].statusCode == 200 &&
response[1].statusCode == 200 &&
response[2].statusCode == 200 &&
response[3].statusCode == 200 &&
response[4].statusCode == 200 &&
response[5].statusCode == 200 &&
response[6].statusCode == 200 &&
response[7].statusCode == 200) {
final summary = v6.StatsSummary.fromJson(jsonDecode(response[0].body));
final infoFtl = v6.InfoFtl.fromJson(jsonDecode(response[1].body));
final blocking = v6.Blocking.fromJson(jsonDecode(response[2].body));
final topPermittedDomains =
v6.StatsTopDomains.fromJson(jsonDecode(response[3].body));
final topBlockedDomains =
v6.StatsTopDomains.fromJson(jsonDecode(response[4].body));
final topClients =
v6.StatsTopClients.fromJson(jsonDecode(response[5].body));
final topBlockedClients =
v6.StatsTopClients.fromJson(jsonDecode(response[6].body));
final upstreams =
v6.StatsUpstreams.fromJson(jsonDecode(response[7].body));

return RealtimeStatusResponse(
result: APiResponseType.success,
data: RealtimeStatus.fromV6(
summary,
infoFtl,
blocking,
topPermittedDomains,
topBlockedDomains,
topClients,
topBlockedClients,
upstreams));
} else {
return RealtimeStatusResponse(result: APiResponseType.error);
}
} on SocketException {
return RealtimeStatusResponse(result: APiResponseType.socket);
} on TimeoutException {
return RealtimeStatusResponse(result: APiResponseType.timeout);
} on HandshakeException {
return RealtimeStatusResponse(result: APiResponseType.sslError);
} catch (e) {
return RealtimeStatusResponse(result: APiResponseType.error);
}
}

/// Disables a Pi-hole server
Expand Down
1 change: 1 addition & 0 deletions lib/models/api/v6/auth/auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Password with _$Password {
class Session with _$Session {
factory Session({
required SessionDetail session,
required double took,
}) = _Session;

factory Session.fromJson(Map<String, dynamic> json) =>
Expand Down
32 changes: 25 additions & 7 deletions lib/models/api/v6/auth/auth.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ Session _$SessionFromJson(Map<String, dynamic> json) {
/// @nodoc
mixin _$Session {
SessionDetail get session => throw _privateConstructorUsedError;
double get took => throw _privateConstructorUsedError;

/// Serializes this Session to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
Expand All @@ -185,7 +186,7 @@ abstract class $SessionCopyWith<$Res> {
factory $SessionCopyWith(Session value, $Res Function(Session) then) =
_$SessionCopyWithImpl<$Res, Session>;
@useResult
$Res call({SessionDetail session});
$Res call({SessionDetail session, double took});

$SessionDetailCopyWith<$Res> get session;
}
Expand All @@ -206,12 +207,17 @@ class _$SessionCopyWithImpl<$Res, $Val extends Session>
@override
$Res call({
Object? session = null,
Object? took = null,
}) {
return _then(_value.copyWith(
session: null == session
? _value.session
: session // ignore: cast_nullable_to_non_nullable
as SessionDetail,
took: null == took
? _value.took
: took // ignore: cast_nullable_to_non_nullable
as double,
) as $Val);
}

Expand All @@ -233,7 +239,7 @@ abstract class _$$SessionImplCopyWith<$Res> implements $SessionCopyWith<$Res> {
__$$SessionImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({SessionDetail session});
$Res call({SessionDetail session, double took});

@override
$SessionDetailCopyWith<$Res> get session;
Expand All @@ -253,43 +259,51 @@ class __$$SessionImplCopyWithImpl<$Res>
@override
$Res call({
Object? session = null,
Object? took = null,
}) {
return _then(_$SessionImpl(
session: null == session
? _value.session
: session // ignore: cast_nullable_to_non_nullable
as SessionDetail,
took: null == took
? _value.took
: took // ignore: cast_nullable_to_non_nullable
as double,
));
}
}

/// @nodoc
@JsonSerializable()
class _$SessionImpl implements _Session {
_$SessionImpl({required this.session});
_$SessionImpl({required this.session, required this.took});

factory _$SessionImpl.fromJson(Map<String, dynamic> json) =>
_$$SessionImplFromJson(json);

@override
final SessionDetail session;
@override
final double took;

@override
String toString() {
return 'Session(session: $session)';
return 'Session(session: $session, took: $took)';
}

@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$SessionImpl &&
(identical(other.session, session) || other.session == session));
(identical(other.session, session) || other.session == session) &&
(identical(other.took, took) || other.took == took));
}

@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, session);
int get hashCode => Object.hash(runtimeType, session, took);

/// Create a copy of Session
/// with the given fields replaced by the non-null parameter values.
Expand All @@ -308,12 +322,16 @@ class _$SessionImpl implements _Session {
}

abstract class _Session implements Session {
factory _Session({required final SessionDetail session}) = _$SessionImpl;
factory _Session(
{required final SessionDetail session,
required final double took}) = _$SessionImpl;

factory _Session.fromJson(Map<String, dynamic> json) = _$SessionImpl.fromJson;

@override
SessionDetail get session;
@override
double get took;

/// Create a copy of Session
/// with the given fields replaced by the non-null parameter values.
Expand Down
2 changes: 2 additions & 0 deletions lib/models/api/v6/auth/auth.g.dart

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

103 changes: 103 additions & 0 deletions lib/models/api/v6/flt/ftl.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'ftl.freezed.dart';
part 'ftl.g.dart';

@freezed
class InfoFtl with _$InfoFtl {
const factory InfoFtl({
required Ftl ftl,
required double took,
}) = _InfoFtl;

factory InfoFtl.fromJson(Map<String, dynamic> json) =>
_$InfoFtlFromJson(json);
}

@freezed
class Ftl with _$Ftl {
const factory Ftl({
required Database database,
@JsonKey(name: 'privacy_level') required int privacyLevel,
required Clients clients,
required int pid,
required int uptime,
@JsonKey(name: '%mem') required double memPercentage,
@JsonKey(name: '%cpu') required double cpuPercentage,
@JsonKey(name: 'allow_destructive') required bool allowDestructive,
required Dnsmasq dnsmasq,
}) = _Ftl;

factory Ftl.fromJson(Map<String, dynamic> json) => _$FtlFromJson(json);
}

@freezed
class Database with _$Database {
const factory Database({
required int gravity,
required int groups,
required int lists,
required int clients,
required Domains domains,
}) = _Database;

factory Database.fromJson(Map<String, dynamic> json) =>
_$DatabaseFromJson(json);
}

@freezed
class Domains with _$Domains {
const factory Domains({
required int allowed,
required int denied,
}) = _Domains;

factory Domains.fromJson(Map<String, dynamic> json) =>
_$DomainsFromJson(json);
}

@freezed
class Clients with _$Clients {
const factory Clients({
required int total,
required int active,
}) = _Clients;

factory Clients.fromJson(Map<String, dynamic> json) =>
_$ClientsFromJson(json);
}

@freezed
class Dnsmasq with _$Dnsmasq {
const factory Dnsmasq({
@JsonKey(name: 'dns_cache_inserted') required int dnsCacheInserted,
@JsonKey(name: 'dns_cache_live_freed') required int dnsCacheLiveFreed,
@JsonKey(name: 'dns_queries_forwarded') required int dnsQueriesForwarded,
@JsonKey(name: 'dns_auth_answered') required int dnsAuthAnswered,
@JsonKey(name: 'dns_local_answered') required int dnsLocalAnswered,
@JsonKey(name: 'dns_stale_answered') required int dnsStaleAnswered,
@JsonKey(name: 'dns_unanswered') required int dnsUnanswered,
@JsonKey(name: 'bootp') required int bootp,
@JsonKey(name: 'pxe') required int pxe,
@JsonKey(name: 'dhcp_ack') required int dhcpAck,
@JsonKey(name: 'dhcp_decline') required int dhcpDecline,
@JsonKey(name: 'dhcp_discover') required int dhcpDiscover,
@JsonKey(name: 'dhcp_inform') required int dhcpInform,
@JsonKey(name: 'dhcp_nak') required int dhcpNak,
@JsonKey(name: 'dhcp_offer') required int dhcpOffer,
@JsonKey(name: 'dhcp_release') required int dhcpRelease,
@JsonKey(name: 'dhcp_request') required int dhcpRequest,
@JsonKey(name: 'noanswer') required int noAnswer,
@JsonKey(name: 'leases_allocated_4') required int leasesAllocated4,
@JsonKey(name: 'leases_pruned_4') required int leasesPruned4,
@JsonKey(name: 'leases_allocated_6') required int leasesAllocated6,
@JsonKey(name: 'leases_pruned_6') required int leasesPruned6,
@JsonKey(name: 'tcp_connections') required int tcpConnections,
@JsonKey(name: 'dnssec_max_crypto_use') required int dnssecMaxCryptoUse,
@JsonKey(name: 'dnssec_max_sig_fail') required int dnssecMaxSigFail,
@JsonKey(name: 'dnssec_max_work') required int dnssecMaxWork,
}) = _Dnsmasq;

factory Dnsmasq.fromJson(Map<String, dynamic> json) =>
_$DnsmasqFromJson(json);
}
Loading

0 comments on commit 3b89474

Please sign in to comment.