22using System . Collections . Generic ;
33using System . IO ;
44using System . Linq ;
5+ using System . Security . Cryptography ;
6+ using System . Text ;
57using System . Text . RegularExpressions ;
68using System . Threading . Tasks ;
79using Azure . Data . Tables ;
@@ -92,16 +94,55 @@ public static List<string> GetListValue(Dictionary<string, object> data, string
9294 return list ;
9395 }
9496
97+ private static string CalculateContentHash ( TipModel tip )
98+ {
99+ // Create a string representation of the content that should be compared for changes
100+ var contentToHash = $ "{ tip . Title } |{ tip . Category } |{ string . Join ( "," , tip . Tags ) } |{ tip . Difficulty } |{ tip . Author } |{ tip . Description } |{ tip . Content } ";
101+ using var sha256 = SHA256 . Create ( ) ;
102+ var hashBytes = sha256 . ComputeHash ( Encoding . UTF8 . GetBytes ( contentToHash ) ) ;
103+ return Convert . ToBase64String ( hashBytes ) ;
104+ }
105+
106+ private static async Task < ContentEntity ? > GetExistingContent ( TableClient tableClient , string partitionKey , string rowKey )
107+ {
108+ try
109+ {
110+ var response = await tableClient . GetEntityAsync < ContentEntity > ( partitionKey , rowKey ) ;
111+ return response . Value ;
112+ }
113+ catch ( Exception )
114+ {
115+ // Entity doesn't exist or other error - treat as not found
116+ return null ;
117+ }
118+ }
119+
95120 public static async Task UploadToTableStorage ( TipModel tip , string connectionString )
96121 {
97122 var serviceClient = new TableServiceClient ( connectionString ) ;
98123 var tableName = "Content" ;
99124 await serviceClient . CreateTableIfNotExistsAsync ( tableName ) ;
100125 var tableClient = serviceClient . GetTableClient ( tableName ) ;
126+
127+ var partitionKey = tip . Category . ToLowerInvariant ( ) ;
128+ var rowKey = ! string . IsNullOrWhiteSpace ( tip . UrlSlug ) ? tip . UrlSlug : tip . FileName ;
129+
130+ // Calculate content hash for change detection
131+ var contentHash = CalculateContentHash ( tip ) ;
132+
133+ // Check if entity already exists
134+ var existingEntity = await GetExistingContent ( tableClient , partitionKey , rowKey ) ;
135+
136+ if ( existingEntity != null && existingEntity . ContentHash == contentHash )
137+ {
138+ Console . WriteLine ( $ "Skipping { tip . FileName } - no changes detected") ;
139+ return ;
140+ }
141+
101142 var entity = new ContentEntity
102143 {
103- PartitionKey = tip . Category . ToLowerInvariant ( ) ,
104- RowKey = ! string . IsNullOrWhiteSpace ( tip . UrlSlug ) ? tip . UrlSlug : tip . FileName ,
144+ PartitionKey = partitionKey ,
145+ RowKey = rowKey ,
105146 Slug = tip . UrlSlug ,
106147 Title = tip . Title ,
107148 Category = tip . Category ,
@@ -111,9 +152,20 @@ public static async Task UploadToTableStorage(TipModel tip, string connectionStr
111152 PublishedDate = DateTime . SpecifyKind ( tip . PublishedDate , DateTimeKind . Utc ) ,
112153 Description = tip . Description ,
113154 Content = tip . Content ,
114- FileName = tip . FileName
155+ FileName = tip . FileName ,
156+ ContentHash = contentHash
115157 } ;
158+
116159 await tableClient . UpsertEntityAsync ( entity ) ;
160+
161+ if ( existingEntity == null )
162+ {
163+ Console . WriteLine ( $ "Uploaded new content: { tip . FileName } ") ;
164+ }
165+ else
166+ {
167+ Console . WriteLine ( $ "Updated changed content: { tip . FileName } ") ;
168+ }
117169 }
118170 }
119171}
0 commit comments