1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . ComponentModel ;
4+ using System . Diagnostics . CodeAnalysis ;
5+ using System . Json ;
6+ using System . Linq ;
7+ using System . Runtime . CompilerServices ;
8+ using System . Security . Authentication ;
9+ using System . Security . Cryptography ;
10+ using System . Security . Policy ;
11+ using System . Text ;
12+ using System . Text . Json ;
13+ using System . Text . Json . Nodes ;
14+ using System . Text . Json . Serialization ;
15+ using System . Threading . Tasks ;
16+ using Flurl . Http ;
17+ using Novus . Streams ;
18+ using SmartImage . Lib . Engines ;
19+ using JsonObject = System . Json . JsonObject ;
20+ using JsonValue = System . Json . JsonValue ;
21+
22+ namespace SmartImage . Lib . Clients ;
23+
24+ public class HydrusClient : IEndpoint , INotifyPropertyChanged
25+ {
26+ private const string HDR_HYDRUS_KEY = "Hydrus-Client-API-Access-Key" ;
27+ private const string GET_FILES_THUMBNAIL = "/get_files/thumbnail" ;
28+ private const string GET_FILES_FILE = "/get_files/file" ;
29+
30+ public FlurlClient Client { get ; }
31+
32+ public HydrusClient ( string endpoint , string key )
33+ {
34+ EndpointUrl = endpoint ;
35+ Key = key ;
36+
37+ Client = new FlurlClient ( EndpointUrl )
38+ {
39+ Headers =
40+ {
41+ { HDR_HYDRUS_KEY , key }
42+ }
43+ } ;
44+
45+ PropertyChanged += ( sender , args ) =>
46+ {
47+ switch ( args . PropertyName )
48+ {
49+ case nameof ( Key ) :
50+ Client . Headers . AddOrReplace ( HDR_HYDRUS_KEY , Key ) ;
51+ break ;
52+ case nameof ( EndpointUrl ) :
53+ Client . BaseUrl = EndpointUrl ;
54+ break ;
55+ }
56+
57+ } ;
58+ }
59+
60+ public HydrusClient ( ) : this ( null , null ) { }
61+
62+ public bool IsValid => EndpointUrl != null && Key != null ;
63+
64+ public async Task < JsonValue > GetFileHashesAsync ( string hash , string hashType = "sha256" )
65+ {
66+
67+ using var res = await Client . Request ( "/get_files/file_hashes" )
68+ . SetQueryParam ( "hash" , hash )
69+ . SetQueryParam ( "source_hash_type" , hashType )
70+ . SetQueryParam ( "desired_hash_type" , hashType )
71+ . GetAsync ( ) ;
72+
73+ var b = await res . GetStreamAsync ( ) ;
74+ var j = JsonValue . Load ( b ) ;
75+ return j ;
76+
77+ }
78+
79+ public async Task < JsonValue > GetFileMetadataAsync ( string hash )
80+ {
81+
82+ using var res = await Client . Request ( "/get_files/file_metadata" )
83+ . SetQueryParam ( "hash" , hash )
84+ . GetAsync ( ) ;
85+
86+ var b = await res . GetStreamAsync ( ) ;
87+ var j = JsonValue . Load ( b ) ;
88+ return j ;
89+ }
90+
91+ public async Task < JsonValue > GetFileRelationshipsAsync ( string hash )
92+ {
93+ using var res = await Client . Request ( "/manage_file_relationships/get_file_relationships" )
94+ . SetQueryParam ( "hash" , hash )
95+ . GetAsync ( ) ;
96+
97+ var b = await res . GetStreamAsync ( ) ;
98+ var j = JsonValue . Load ( b ) ;
99+
100+ return j ;
101+ }
102+
103+ public async Task < IFlurlResponse > GetFileAsync ( string hash )
104+ {
105+ var res = await Client . Request ( GET_FILES_FILE )
106+ . SetQueryParam ( "hash" , hash )
107+ . GetAsync ( ) ;
108+
109+ return res ;
110+ }
111+ public async Task < IFlurlResponse > GetFileAsync ( int id )
112+ {
113+ var res = await Client . Request ( GET_FILES_FILE )
114+ . SetQueryParam ( "file_id" , id )
115+ . GetAsync ( ) ;
116+
117+ return res ;
118+ }
119+ public async Task < IFlurlResponse > GetFileThumbnailAsync ( string hash )
120+ {
121+ var res = await Client . Request ( GET_FILES_THUMBNAIL )
122+ . SetQueryParam ( "hash" , hash )
123+ . GetAsync ( ) ;
124+
125+ return res ;
126+ }
127+
128+ public async Task < IFlurlResponse > GetFileThumbnailAsync ( int id )
129+ {
130+ var res = await Client . Request ( GET_FILES_THUMBNAIL )
131+ . SetQueryParam ( "file_id" , id )
132+ . GetAsync ( ) ;
133+
134+ return res ;
135+ }
136+
137+ private string m_key ;
138+
139+ public string Key
140+ {
141+ get => m_key ;
142+ set
143+ {
144+ if ( value == m_key ) return ;
145+ m_key = value ;
146+ OnPropertyChanged ( ) ;
147+ OnPropertyChanged ( nameof ( IsValid ) ) ;
148+ }
149+ }
150+
151+ private string m_endpointUrl ;
152+
153+ public string EndpointUrl
154+ {
155+ get => m_endpointUrl ;
156+ set
157+ {
158+ if ( value == m_endpointUrl ) return ;
159+ m_endpointUrl = value ;
160+ OnPropertyChanged ( ) ;
161+ OnPropertyChanged ( nameof ( IsValid ) ) ;
162+ }
163+ }
164+
165+ public void Dispose ( )
166+ {
167+ Client . Dispose ( ) ;
168+ }
169+
170+ public event PropertyChangedEventHandler PropertyChanged ;
171+
172+ protected virtual void OnPropertyChanged ( [ CallerMemberName ] string propertyName = null )
173+ {
174+ PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( propertyName ) ) ;
175+ }
176+
177+ protected bool SetField < T > ( ref T field , T value , [ CallerMemberName ] string propertyName = null )
178+ {
179+ if ( EqualityComparer < T > . Default . Equals ( field , value ) ) return false ;
180+ field = value ;
181+ OnPropertyChanged ( propertyName ) ;
182+ return true ;
183+ }
184+ }
185+
186+ public partial class FileRelationship
187+ {
188+ [ JsonPropertyName ( "0" ) ]
189+ public string [ ] PotentialDuplicates { get ; set ; }
190+
191+ [ JsonPropertyName ( "1" ) ]
192+ public string [ ] FalsePositives { get ; set ; }
193+
194+ [ JsonPropertyName ( "3" ) ]
195+ public string [ ] Alternates { get ; set ; }
196+
197+ [ JsonPropertyName ( "8" ) ]
198+ public string [ ] Duplicates { get ; set ; }
199+
200+ [ JsonPropertyName ( "is_king" ) ]
201+ public bool IsKing { get ; set ; }
202+
203+ [ JsonPropertyName ( "king" ) ]
204+ public string King { get ; set ; }
205+
206+ [ JsonPropertyName ( "king_is_local" ) ]
207+ public bool KingIsLocal { get ; set ; }
208+
209+ [ JsonPropertyName ( "king_is_on_file_domain" ) ]
210+ public bool KingIsOnFileDomain { get ; set ; }
211+
212+ public static Dictionary < string , FileRelationship > Deserialize ( JsonValue v )
213+ {
214+ var vs = ( ( JsonObject ) v ) [ "file_relationships" ] ;
215+
216+ var re = JsonSerializer . Deserialize < Dictionary < string , FileRelationship > > ( vs . ToString ( ) ) ;
217+
218+ return re ;
219+ }
220+ }
0 commit comments