update bangs

This commit is contained in:
Fabian Freund
2026-03-27 19:55:11 +01:00
parent 7253470715
commit e27eda6be6
16 changed files with 3670 additions and 23 deletions
+24 -4
View File
@@ -21,6 +21,7 @@ import 'package:copy_with_extension/copy_with_extension.dart';
import 'package:drift/drift.dart' show Expression, Insertable, Value;
import 'package:fast_equatable/fast_equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:nullability/nullability.dart';
import 'package:weblibre/extensions/uri.dart';
import 'package:weblibre/features/bangs/data/database/definitions.drift.dart';
import 'package:weblibre/features/bangs/data/models/bang_group.dart';
@@ -42,6 +43,10 @@ enum BangFormat {
///with one or the other.
@JsonValue('url_encode_space_to_plus')
urlEncodeSpaceToPlus,
///When the bang is invoked with no query, open the snap domain (ad) instead of any path given in the template
@JsonValue('open_snap_domain')
openSnapDomain,
}
@JsonSerializable()
@@ -84,6 +89,10 @@ class Bang with FastEquatable implements Insertable<Bang> {
@JsonKey(name: 'ts')
final Set<String>? additionalTriggers;
///Additional triggers that invoke this bang
@JsonKey(name: 'ad')
final String? snapDomain;
@JsonKey(defaultValue: false)
final bool searxngApi;
@@ -102,8 +111,16 @@ class Bang with FastEquatable implements Insertable<Bang> {
}
Uri getTemplateUrl(String? query) {
final url = (query != null)
? urlTemplate.replaceAll(_templateQueryPlaceholder, formatQuery(query))
final queryEmpty = query.isEmpty;
if (queryEmpty && format?.contains(BangFormat.openSnapDomain) == true) {
if (snapDomain.isNotEmpty) {
return Uri.parse(snapDomain!);
}
}
final url = (!queryEmpty)
? urlTemplate.replaceAll(_templateQueryPlaceholder, formatQuery(query!))
: urlTemplate;
var template = Uri.parse(url);
@@ -113,8 +130,8 @@ class Bang with FastEquatable implements Insertable<Bang> {
).replace(path: template.path, query: template.query);
}
if (format?.contains(BangFormat.openBasePath) == true) {
return template.base;
if (queryEmpty && format?.contains(BangFormat.openBasePath) == true) {
template = template.base;
}
return template;
@@ -139,6 +156,7 @@ class Bang with FastEquatable implements Insertable<Bang> {
this.subCategory,
this.format,
this.additionalTriggers,
this.snapDomain,
});
factory Bang.fromJson(Map<String, dynamic> json) => _$BangFromJson(json);
@@ -156,6 +174,7 @@ class Bang with FastEquatable implements Insertable<Bang> {
subCategory,
format,
additionalTriggers,
snapDomain,
searxngApi,
];
@@ -171,6 +190,7 @@ class Bang with FastEquatable implements Insertable<Bang> {
subCategory: Value.absentIfNull(subCategory),
format: Value.absentIfNull(format),
additionalTriggers: Value.absentIfNull(additionalTriggers),
snapDomain: Value.absentIfNull(snapDomain),
).toColumns(nullToAbsent);
}
}
@@ -27,6 +27,8 @@ abstract class _$BangCWProxy {
Bang additionalTriggers(Set<String>? additionalTriggers);
Bang snapDomain(String? snapDomain);
/// Creates a new instance with the provided field values.
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `Bang(...).copyWith.fieldName(value)`.
///
@@ -45,6 +47,7 @@ abstract class _$BangCWProxy {
String? subCategory,
Set<BangFormat>? format,
Set<String>? additionalTriggers,
String? snapDomain,
});
}
@@ -86,6 +89,9 @@ class _$BangCWProxyImpl implements _$BangCWProxy {
Bang additionalTriggers(Set<String>? additionalTriggers) =>
call(additionalTriggers: additionalTriggers);
@override
Bang snapDomain(String? snapDomain) => call(snapDomain: snapDomain);
@override
/// Creates a new instance with the provided field values.
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `Bang(...).copyWith.fieldName(value)`.
@@ -105,6 +111,7 @@ class _$BangCWProxyImpl implements _$BangCWProxy {
Object? subCategory = const $CopyWithPlaceholder(),
Object? format = const $CopyWithPlaceholder(),
Object? additionalTriggers = const $CopyWithPlaceholder(),
Object? snapDomain = const $CopyWithPlaceholder(),
}) {
return Bang(
websiteName:
@@ -150,6 +157,10 @@ class _$BangCWProxyImpl implements _$BangCWProxy {
? _value.additionalTriggers
// ignore: cast_nullable_to_non_nullable
: additionalTriggers as Set<String>?,
snapDomain: snapDomain == const $CopyWithPlaceholder()
? _value.snapDomain
// ignore: cast_nullable_to_non_nullable
: snapDomain as String?,
);
}
}
@@ -179,6 +190,7 @@ Bang _$BangFromJson(Map<String, dynamic> json) => Bang(
additionalTriggers: (json['ts'] as List<dynamic>?)
?.map((e) => e as String)
.toSet(),
snapDomain: json['ad'] as String?,
);
Map<String, dynamic> _$BangToJson(Bang instance) => <String, dynamic>{
@@ -190,6 +202,7 @@ Map<String, dynamic> _$BangToJson(Bang instance) => <String, dynamic>{
'sc': instance.subCategory,
'fmt': instance.format?.map((e) => _$BangFormatEnumMap[e]!).toList(),
'ts': instance.additionalTriggers?.toList(),
'ad': instance.snapDomain,
'searxngApi': instance.searxngApi,
};
@@ -197,4 +210,5 @@ const _$BangFormatEnumMap = {
BangFormat.openBasePath: 'open_base_path',
BangFormat.urlEncodePlaceholder: 'url_encode_placeholder',
BangFormat.urlEncodeSpaceToPlus: 'url_encode_space_to_plus',
BangFormat.openSnapDomain: 'open_snap_domain',
};
@@ -46,6 +46,7 @@ class BangData extends Bang {
super.subCategory,
super.format,
super.additionalTriggers,
super.snapDomain,
int? frequency,
this.lastUsed,
this.icon,
@@ -62,6 +63,7 @@ class BangData extends Bang {
super.subCategory,
super.format,
super.additionalTriggers,
super.snapDomain,
int? frequency,
this.lastUsed,
this.icon,
@@ -25,6 +25,8 @@ abstract class _$BangDataCWProxy {
BangData additionalTriggers(Set<String>? additionalTriggers);
BangData snapDomain(String? snapDomain);
BangData frequency(int? frequency);
BangData lastUsed(DateTime? lastUsed);
@@ -48,6 +50,7 @@ abstract class _$BangDataCWProxy {
String? subCategory,
Set<BangFormat>? format,
Set<String>? additionalTriggers,
String? snapDomain,
int? frequency,
DateTime? lastUsed,
BrowserIcon? icon,
@@ -89,6 +92,9 @@ class _$BangDataCWProxyImpl implements _$BangDataCWProxy {
BangData additionalTriggers(Set<String>? additionalTriggers) =>
call(additionalTriggers: additionalTriggers);
@override
BangData snapDomain(String? snapDomain) => call(snapDomain: snapDomain);
@override
BangData frequency(int? frequency) => call(frequency: frequency);
@@ -116,6 +122,7 @@ class _$BangDataCWProxyImpl implements _$BangDataCWProxy {
Object? subCategory = const $CopyWithPlaceholder(),
Object? format = const $CopyWithPlaceholder(),
Object? additionalTriggers = const $CopyWithPlaceholder(),
Object? snapDomain = const $CopyWithPlaceholder(),
Object? frequency = const $CopyWithPlaceholder(),
Object? lastUsed = const $CopyWithPlaceholder(),
Object? icon = const $CopyWithPlaceholder(),
@@ -160,6 +167,10 @@ class _$BangDataCWProxyImpl implements _$BangDataCWProxy {
? _value.additionalTriggers
// ignore: cast_nullable_to_non_nullable
: additionalTriggers as Set<String>?,
snapDomain: snapDomain == const $CopyWithPlaceholder()
? _value.snapDomain
// ignore: cast_nullable_to_non_nullable
: snapDomain as String?,
frequency: frequency == const $CopyWithPlaceholder()
? _value.frequency
// ignore: cast_nullable_to_non_nullable
@@ -23,11 +23,6 @@ enum BangGroup {
'https://raw.githubusercontent.com/FaFre/bangs/main/data/bangs.json',
bundled: 'assets/bangs/bangs.json',
),
assistant(
remote:
'https://raw.githubusercontent.com/FaFre/bangs/main/data/assistant_bangs.json',
bundled: 'assets/bangs/assistant_bangs.json',
),
kagi(
remote:
'https://raw.githubusercontent.com/FaFre/bangs/main/data/kagi_bangs.json',
@@ -46,7 +46,13 @@ class BangKey {
static BangKey? tryFromString(String key) {
try {
final [group, trigger] = key.split('::');
var [group, trigger] = key.split('::');
//Migrate to schema v5
if (group == 'assistant') {
group = BangGroup.kagi.name;
}
return BangKey(
group: BangGroup.values.firstWhere((g) => g.name == group),
trigger: trigger,