From 940c4c8d2e43ec0de46ede870071fe9d86ade735 Mon Sep 17 00:00:00 2001
From: Jan Eggers <janeggers@untergeekPro.local>
Date: Tue, 31 Dec 2024 11:18:00 +0100
Subject: [PATCH] Paket eingerichtet

---
 main.py                                       | 69 +++++++++++++++++++
 pyproject.toml                                | 22 ++++++
 __init__.py => src/__init__.py                |  0
 .../bildbeschreibung.py                       |  3 -
 check_bsky_profile.py => src/check_bsky.py    |  6 +-
 detectora.py => src/detectora.py              |  0
 imagecheck.py => src/imagecheck.py            |  2 +-
 7 files changed, 95 insertions(+), 7 deletions(-)
 create mode 100644 main.py
 create mode 100644 pyproject.toml
 rename __init__.py => src/__init__.py (100%)
 rename bildbeschreibung.py => src/bildbeschreibung.py (98%)
 rename check_bsky_profile.py => src/check_bsky.py (98%)
 rename detectora.py => src/detectora.py (100%)
 rename imagecheck.py => src/imagecheck.py (97%)

diff --git a/main.py b/main.py
new file mode 100644
index 0000000..f6f31c8
--- /dev/null
+++ b/main.py
@@ -0,0 +1,69 @@
+# Proof-of-concept: KI-Check von Bluesky-Konten
+#
+# 12-2024 Jan Eggers
+
+from src.check_bsky import *
+
+# Konstante 
+d_thresh = .8 # 80 Prozent 
+limit = 25 # Posts für den Check
+
+if __name__ == "__main__":
+    # Bluesky-Check
+    handle_str = input("Erstes Handle mit diesen Zeichen wählen: ")
+    handle = find_handles(handle_str)[0]
+    print(handle)
+    # Diese Funktion holt die Infos zum Profil 'handle':
+    # Erwartet einen String, gibt ein dict zurück. 
+    # Beschreibung: https://docs.bsky.app/docs/api/app-bsky-actor-get-profile
+    # Manchmal existieren Felder wie 'description' nicht. 
+    profile = call_get_profile(handle)
+    author = profile['did']
+    print(author)
+    # Diese Funktion holt die Posts.
+    # 'author' darf irgendwas sein: handle, did... wir nehmen die did
+    # Gibt ein dict zurück: im Schlüssel 'feed' sind die einzelnen Posts gespeichert, 
+    # im Key 'cursor' gibt es das Datum des frühesten abgefragten Posts zurück (es sei denn,
+    # es sind weniger Posts als limit, dann ist cursor leer.)
+    # Beschreibung: https://docs.bsky.app/docs/api/app-bsky-feed-get-author-feed 
+    posts = call_get_author_feed(author, limit = limit)
+    # In diesem Demo-Programm werden die Posts hier noch nicht ausgewertet. 
+    # Das passiert in der Extra-Funktion check_handle unten.
+    print(posts['cursor'])
+    # Funktion prüft die letzten ```limit``` Posts (voreingestellt auf 20)
+    # Erwartet ein Handle oder ein did  - wir nehmen DID
+    # Gibt ein Dataframe zurück; Struktur ist oben in der Funktion beschrieben. 
+    # Wichtigster Punkt: Ergebnis des KI-Checks in den Spalten
+    # - 'detectora_ai_score': Detectora-Score des Post-Textes (als real)
+    # - 'aiornot_ai_score': 
+    df = check_handle(author, limit = limit)
+    n_posts = len(df)
+    print(f'\n\nAnalyse des Kontos @{handle} ({profile['displayName']}) seit {profile['createdAt']}- {profile['followersCount']} Follower')
+    print(f'{profile.get('description','---')}\n')
+    print(f'Anzahl der analysierten Posts: {n_posts}')
+    print(f"Durchschnittliche KI-Text-Wahrscheinlichkeit: {df['detectora_ai_score'].mean()}")
+    detectora_posts_df = df[df['detectora_ai_score'] >= d_thresh]
+    print(f"Anzahl von Posts über einer detectora-Schwelle von {d_thresh*100:.1f}%: {len(detectora_posts_df)}")
+    image_posts = [post for post in df['aiornot_ai_score'].to_list() if post is not None]
+    # Liste auspacken, nur die Dicts ohne None-Elemente
+    image_list = [item for sublist in image_posts for item in sublist]
+    ai_list = [item for item in image_list if item['aiornot_score']!='human']
+    if len(image_list) == 0: 
+        p_ai = 0
+    else: 
+        p_ai = len(ai_list)/len(image_list) * 100
+    print(f"Anzahl der Bilder: {len(image_list)}, verdächtig: {len(ai_list)} ({p_ai:.1f})%")
+    # Jetzt die Daten abspeichern
+    # Fals das Directory nicht existiert, anlegen
+    if not os.path.exists('bsky-checks'):
+        os.makedirs('bsky-checks')
+        
+    # Read existing file if it exists
+    filename = f'bsky-checks/{handle}.csv'
+    if os.path.exists(filename):
+        existing_df = pd.read_csv(filename)
+        df = pd.concat([existing_df, df]).drop_duplicates(subset=['uri']).reset_index(drop=True)
+    
+    df.to_csv(f'bsky-checks/{handle}.csv', index=False)  # Save to CSV for example
+    
+    
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..bcc95da
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,22 @@
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[project]
+name = "aichecker"
+version = "0.1.0"
+description = "Bluesky-Konten auf KI-Inhalte checken"
+requires-python = ">=3.8"
+dependencies = [
+    "requests", # Alle bsky-Calls über Requests
+    "openai", # für die Bildbeschreibung
+    "ollama", # für die Bildbeschreibung
+]
+
+[project.optional-dependencies]
+dev = [
+    "pytest",
+]
+
+[tool.hatch.build.targets.wheel]
+packages = ["src"]
\ No newline at end of file
diff --git a/__init__.py b/src/__init__.py
similarity index 100%
rename from __init__.py
rename to src/__init__.py
diff --git a/bildbeschreibung.py b/src/bildbeschreibung.py
similarity index 98%
rename from bildbeschreibung.py
rename to src/bildbeschreibung.py
index 548c1c2..924fb18 100644
--- a/bildbeschreibung.py
+++ b/src/bildbeschreibung.py
@@ -1,8 +1,5 @@
-import re
-import locale
 import ollama
 from openai import OpenAI
-import whisper
 from pathlib import Path
 import os
 import base64
diff --git a/check_bsky_profile.py b/src/check_bsky.py
similarity index 98%
rename from check_bsky_profile.py
rename to src/check_bsky.py
index 266baf4..77a0b14 100644
--- a/check_bsky_profile.py
+++ b/src/check_bsky.py
@@ -5,9 +5,9 @@
 
 import json
 import pandas as pd
-from detectora import query_detectora
-from imagecheck import query_aiornot
-from bildbeschreibung import gpt4_description
+from .detectora import query_detectora
+from .imagecheck import query_aiornot
+from .bildbeschreibung import gpt4_description
 import requests
 import os
 
diff --git a/detectora.py b/src/detectora.py
similarity index 100%
rename from detectora.py
rename to src/detectora.py
diff --git a/imagecheck.py b/src/imagecheck.py
similarity index 97%
rename from imagecheck.py
rename to src/imagecheck.py
index e6c2e85..6ebc733 100644
--- a/imagecheck.py
+++ b/src/imagecheck.py
@@ -1,6 +1,6 @@
 # imagecheck.py
 # Erfragt KI-Wahrscheinlichkeit für ein Bild über Hive- und AIorNot-API
-from bildbeschreibung import ai_description
+from src.bildbeschreibung import ai_description
 
 import requests
 import json
-- 
GitLab