-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFetchTags.py
More file actions
144 lines (117 loc) · 4.4 KB
/
FetchTags.py
File metadata and controls
144 lines (117 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import requests
import json
import concurrent.futures
import time
from tqdm import tqdm
from rich.console import Console
# AnkiConnect URL
ANKI_CONNECT_URL = "http://localhost:8765"
# Your deck name
DECK_NAME = "Personal word bank"
# Field names
WORD_FIELD = "Front" # The field where the Japanese word is stored
TYPE_FIELD = "Tags" # The field where we will store the word type
# Console for refreshing CLI
console = Console()
def get_notes_from_deck(deck_name):
"""Retrieve note IDs from a given deck."""
payload = {
"action": "findNotes",
"version": 6,
"params": {"query": f'deck:"{deck_name}"'}
}
try:
response = requests.post(ANKI_CONNECT_URL, json=payload)
response.raise_for_status()
result = response.json()
return result.get("result", [])
except requests.RequestException as e:
print(f"Error fetching notes from deck: {e}")
return []
def get_note_info(note_ids):
"""Retrieve note info including fields."""
payload = {
"action": "notesInfo",
"version": 6,
"params": {"notes": note_ids}
}
try:
response = requests.post(ANKI_CONNECT_URL, json=payload)
response.raise_for_status()
result = response.json()
return result.get("result", [])
except requests.RequestException as e:
print(f"Error fetching note info: {e}")
return []
def get_word_type(word, progress_bar):
"""Fetch word type from Jisho.org API."""
url = f"https://jisho.org/api/v1/search/words?keyword={word}"
try:
response = requests.get(url)
response.raise_for_status()
result = response.json()
# Extract part of speech if available
if result["data"]:
senses = result["data"][0].get("senses", [])
if senses:
return ", ".join(senses[0].get("parts_of_speech", [])) # Get first part of speech
return "Unknown" # If not found
except requests.RequestException as e:
if response.status_code == 429:
progress_bar.set_description(f"Rate limit exceeded. Sleeping for a while before retrying...")
time.sleep(5) # Sleep for 5 seconds before retrying
return get_word_type(word, progress_bar) # Retry fetching the word type
print(f"Error fetching word type from Jisho.org: {e}")
return "Unknown"
def update_word_type(note_id, word_type):
"""Update the 'Word Type' field in Anki and return the status of the update."""
payload = {
"action": "updateNoteFields",
"version": 6,
"params": {
"note": {
"id": note_id,
"fields": {
TYPE_FIELD: word_type
}
}
}
}
try:
response = requests.post(ANKI_CONNECT_URL, json=payload)
response.raise_for_status()
result = response.json()
# Check for success or failure based on the response
if result.get("error") is None:
return True
else:
print(f"Failed to update note {note_id}: {result.get('error')}")
return False
except requests.RequestException as e:
print(f"Error updating word type in Anki: {e}")
return False
def process_note_with_progress(note, progress_bar):
"""Process a single note, fetch word type, update Anki, and update the progress bar status."""
word = note["fields"].get(WORD_FIELD, {}).get("value", "").strip()
if not word:
return
word_type = get_word_type(word, progress_bar)
update_word_type(note["noteId"], word_type)
progress_bar.set_description(f"Processing: {word} -> {word_type}")
progress_bar.update(1)
def main():
print("Fetching cards from Anki...")
note_ids = get_notes_from_deck(DECK_NAME)
if not note_ids:
print("No cards found.")
return
notes = get_note_info(note_ids)
console.print("Processing notes...")
with tqdm(total=len(notes), desc="Processing notes") as progress_bar:
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(process_note_with_progress, note, progress_bar) for note in notes]
for future in concurrent.futures.as_completed(futures):
future.result() # Ensure all tasks are completed
print("✅ Word type update complete!")
if __name__ == "__main__":
main()