Mastodon: Implemented OCR for images in posts

This commit is contained in:
Manuel Cortez 2023-04-05 12:57:37 -06:00
parent db4607f17e
commit 00a5ad9e59
No known key found for this signature in database
GPG Key ID: 9E0735CA15EFE790
6 changed files with 76 additions and 5 deletions

View File

@ -7,6 +7,7 @@ During the development of the current TWBlue version, Twitter has cut out access
* TWBlue should be able to display variables within templates (for example, now it is possible to send a template inside a post's text). Before, it was removing $variables so it was difficult to show how to edit templates from the client. ([#515](https://github.com/MCV-Software/TWBlue/issues/515)) * TWBlue should be able to display variables within templates (for example, now it is possible to send a template inside a post's text). Before, it was removing $variables so it was difficult to show how to edit templates from the client. ([#515](https://github.com/MCV-Software/TWBlue/issues/515))
* Mastodon: * Mastodon:
* it is possible to add descriptions for all media available on Mastodon (audio, photos, video and Givs). ([#516](https://github.com/MCV-Software/TWBlue/issues/516)) * it is possible to add descriptions for all media available on Mastodon (audio, photos, video and Givs). ([#516](https://github.com/MCV-Software/TWBlue/issues/516))
* TWBlue can now perform OCR in attached images.
* Implemented "Hide emojis on usernames" in both GUI and invisible interface. * Implemented "Hide emojis on usernames" in both GUI and invisible interface.
* Added an experimental feature to recover from connection errors. When making a post, if the post cannot be published due to any kind of error, TWBlue will bring up the dialog where the post was composed, so you can give the post a second chance or save the post's text. This feature should work for threads, posts with attachments, polls and replies. ([#527,](https://github.com/MCV-Software/TWBlue/issues/527) [#526,](https://github.com/MCV-Software/TWBlue/issues/526) [#377,](https://github.com/MCV-Software/TWBlue/issues/377) [#137,](https://github.com/MCV-Software/TWBlue/issues/137) [#108](https://github.com/MCV-Software/TWBlue/issues/108)) * Added an experimental feature to recover from connection errors. When making a post, if the post cannot be published due to any kind of error, TWBlue will bring up the dialog where the post was composed, so you can give the post a second chance or save the post's text. This feature should work for threads, posts with attachments, polls and replies. ([#527,](https://github.com/MCV-Software/TWBlue/issues/527) [#526,](https://github.com/MCV-Software/TWBlue/issues/526) [#377,](https://github.com/MCV-Software/TWBlue/issues/377) [#137,](https://github.com/MCV-Software/TWBlue/issues/137) [#108](https://github.com/MCV-Software/TWBlue/issues/108))
* When playing media items, TWBlue will prefer remote URL streams and fall back to instance cached stream URL'S. * When playing media items, TWBlue will prefer remote URL streams and fall back to instance cached stream URL'S.

View File

@ -413,7 +413,6 @@ class BaseBuffer(base.Buffer):
item = self.get_item() item = self.get_item()
if item == None: if item == None:
return return
print(item)
urls = utils.get_media_urls(item) urls = utils.get_media_urls(item)
if len(urls) == 1: if len(urls) == 1:
url=urls[0] url=urls[0]
@ -542,7 +541,41 @@ class BaseBuffer(base.Buffer):
def ocr_image(self): def ocr_image(self):
post = self.get_item() post = self.get_item()
media_list = [] media_list = []
pass if post.reblog != None:
post = post.reblog
for media in post.get("media_attachments"):
if media.get("type", "") == "image":
media_list.append(media)
if len(media_list) > 1:
image_list = [_(u"Picture {0}").format(i+1,) for i in range(0, len(media_list))]
dialog = urlList.urlList(title=_(u"Select the picture"))
dialog.populate_list(image_list)
if dialog.get_response() == widgetUtils.OK:
img = media_list[dialog.get_item()]
else:
return
elif len(media_list) == 1:
img = media_list[0]
else:
return
if self.session.settings["mysc"]["ocr_language"] != "":
ocr_lang = self.session.settings["mysc"]["ocr_language"]
else:
ocr_lang = ocr.OCRSpace.short_langs.index(post.language)
ocr_lang = ocr.OCRSpace.OcrLangs[ocr_lang]
if img["remote_url"] != None:
url = img["remote_url"]
else:
url = img["url"]
api = ocr.OCRSpace.OCRSpaceAPI()
try:
text = api.OCR_URL(url)
except ocr.OCRSpace.APIError as er:
output.speak(_(u"Unable to extract text"))
return
viewer = messages.text(title=_("OCR Result"), text=text["ParsedText"])
response = viewer.message.ShowModal()
viewer.message.Destroy()
def vote(self): def vote(self):
post = self.get_item() post = self.get_item()

View File

@ -30,7 +30,7 @@ class Handler(object):
unfav=_("Remove from favorites"), unfav=_("Remove from favorites"),
view=_("&Show post"), view=_("&Show post"),
view_conversation=_("View conversa&tion"), view_conversation=_("View conversa&tion"),
ocr=None, ocr=_("Read text in picture"),
delete=_("&Delete"), delete=_("&Delete"),
# In user menu. # In user menu.
follow=_("&Actions..."), follow=_("&Actions..."),

View File

@ -270,3 +270,11 @@ class viewPost(post):
if hasattr(self, "item_url"): if hasattr(self, "item_url"):
output.copy(self.item_url) output.copy(self.item_url)
output.speak(_("Link copied to clipboard.")) output.speak(_("Link copied to clipboard."))
class text(messages.basicMessage):
def __init__(self, title, text="", *args, **kwargs):
self.title = title
self.message = postDialogs.viewText(title=title, text=text, *args, **kwargs)
self.message.text.SetInsertionPoint(len(self.message.text.GetValue()))
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)

View File

@ -52,6 +52,6 @@ actions = {
"accountConfiguration": _(u"Opens the account settings dialogue"), "accountConfiguration": _(u"Opens the account settings dialogue"),
"audio": _(u"Try to play a media file"), "audio": _(u"Try to play a media file"),
"update_buffer": _(u"Updates the buffer and retrieves possible lost items there."), "update_buffer": _(u"Updates the buffer and retrieves possible lost items there."),
# "ocr_image": _(u"Extracts the text from a picture and displays the result in a dialog."), "ocr_image": _(u"Extracts the text from a picture and displays the result in a dialog."),
# "add_alias": _("Adds an alias to an user"), # "add_alias": _("Adds an alias to an user"),
} }

View File

@ -255,6 +255,34 @@ class viewPost(wx.Dialog):
if hasattr(self, buttonName): if hasattr(self, buttonName):
return getattr(self, buttonName).Enable() return getattr(self, buttonName).Enable()
class viewPost(wx.Dialog):
def set_title(self, lenght):
self.SetTitle(_("Post - %i characters ") % (lenght,))
class viewText(wx.Dialog):
def __init__(self, title="", text="", *args, **kwargs):
super(viewText, self).__init__(parent=None, id=wx.ID_ANY, size=(850,850), title=title)
panel = wx.Panel(self)
label = wx.StaticText(panel, -1, _("Text"))
self.text = wx.TextCtrl(panel, -1, text, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(250, 180))
self.text.SetFocus()
textBox = wx.BoxSizer(wx.HORIZONTAL)
textBox.Add(label, 0, wx.ALL, 5)
textBox.Add(self.text, 1, wx.EXPAND, 5)
mainBox = wx.BoxSizer(wx.VERTICAL)
mainBox.Add(textBox, 0, wx.ALL, 5)
self.spellcheck = wx.Button(panel, -1, _("Check &spelling..."), size=wx.DefaultSize)
self.translateButton = wx.Button(panel, -1, _(u"&Translate..."), size=wx.DefaultSize)
cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"C&lose"), size=wx.DefaultSize)
cancelButton.SetDefault()
buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
buttonsBox.Add(self.spellcheck, 0, wx.ALL, 5)
buttonsBox.Add(self.translateButton, 0, wx.ALL, 5)
buttonsBox.Add(cancelButton, 0, wx.ALL, 5)
mainBox.Add(buttonsBox, 0, wx.ALL, 5)
panel.SetSizer(mainBox)
self.SetClientSize(mainBox.CalcMin())
class poll(wx.Dialog): class poll(wx.Dialog):
def __init__(self, *args, **kwds): def __init__(self, *args, **kwds):
super(poll, self).__init__(parent=None, id=wx.NewId(), title=_("Add a poll")) super(poll, self).__init__(parent=None, id=wx.NewId(), title=_("Add a poll"))
@ -366,3 +394,4 @@ class attachedPoll(wx.Dialog):
if getattr(self, "option{}".format(option)).GetValue() == True: if getattr(self, "option{}".format(option)).GetValue() == True:
options.append(option) options.append(option)
return options return options