Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
27abe19
Update links from google to readthedocs
Jan 14, 2021
9602f7c
Various bugfixes
Jan 14, 2021
c569731
Django update to 1.11
Jan 14, 2021
29ab175
Update urls.py
Jan 14, 2021
20c4917
Update communication.py
Jan 15, 2021
e4b04b1
media folder
Jan 15, 2021
6e9e782
versions shown on home screen
Jan 15, 2021
059cc84
Update webserver.py
Jan 15, 2021
84db803
Merge branch 'bugfixes'
Jan 15, 2021
c371c45
Merge branch 'django-updates'
Jan 15, 2021
eb80a7c
More django update fixes
Jan 22, 2021
bdbdab3
Merge branch 'django-updates'
Jan 22, 2021
be4230f
Update communication.py
Jan 22, 2021
88bd2ae
Update engine.py
Jan 22, 2021
1678b57
Merge branch 'bugfixes'
Jan 22, 2021
06e4a32
Merge branch 'bugfixes' into python3-mike
Jan 22, 2021
b50ed69
Merge branch 'master' into python3-mike
Jan 22, 2021
26ead63
Python 3 changes
Jan 22, 2021
36aef22
Merge branch 'master' into django-updates
BikeMikeAU Jan 22, 2021
7f45a6d
Update bots.ini
Jan 23, 2021
cbf29ac
Django template html changes
Feb 4, 2021
91d209a
reset failure counter after a successful connection
Feb 4, 2021
3d4ed29
Record activate/deactivate actions in Django object history
Feb 4, 2021
f36e2c4
sftp updates
Feb 4, 2021
94232a7
check the version after import
Feb 4, 2021
f2eec06
Fix up maxconnectiontries logic in run()
Feb 5, 2021
4bf4942
exception shows paramiiko version installed if < 2.0
Feb 5, 2021
98b1efe
Merge branch 'django-updates' into enhancements
Feb 11, 2021
45f81bd
Merge branch 'bugfixes' into enhancements
Feb 11, 2021
42504a8
Merge branch 'sftp' into enhancements
Feb 11, 2021
176b2aa
Use Django pluralize filter for run reports
Feb 11, 2021
ae1ceee
ccode tables upload/download to csv
Feb 12, 2021
1a1de49
add botskey to detail view
Feb 12, 2021
a152fd2
Update paginator.html
Feb 12, 2021
695040c
Plugin creation with filtered subset
Feb 12, 2021
b30b621
Add indent_xml and indent-json
Feb 12, 2021
98b848c
Option to show or hide "change password" and "run cleanup" in menu
Feb 12, 2021
eb12261
Settings for daily log file, environment
Feb 12, 2021
9eed100
dirmonitor timeout setting in bots.ini
Feb 12, 2021
48d83b8
jobqueue changes (configurable)
Feb 12, 2021
2b27bcb
Add route groups for easier scheduling
Feb 12, 2021
5ae880b
admin: option for save buttons on top. Add links to channels in routes
Feb 12, 2021
57c6941
setting for daily logging
Feb 12, 2021
0f9b300
Py3 exception context for script imports
Feb 12, 2021
a535de7
expand username and secret fields
Feb 12, 2021
b133db7
add filename parameter to accept_incoming_attachment
Feb 12, 2021
a6e0ea7
catch errors when trying to display logfiles
Feb 12, 2021
4fedd2c
improve test email, with success/failure notification on screen
Feb 12, 2021
de27dec
fix indent settings.py
Feb 12, 2021
5f3def9
Version number 4.0
Feb 12, 2021
3537621
Update engine.py
Feb 12, 2021
8d62bdd
round elapsed seconds to 1 decimal
Feb 12, 2021
608d73c
Fix date-time picker widget on select form
Feb 15, 2021
3e2559d
jquery-ui-icons updated and moved
Feb 15, 2021
e1b6154
fix browser window title
Feb 15, 2021
646fb92
replace terms whitelist and blacklist with allowlist and blocklist
Feb 15, 2021
b772ca4
further enhancement of ccode upload from csv
Feb 16, 2021
223e3b8
Django 3 updates
Feb 19, 2021
d62caf2
bots_ordereddict is no longer needed
Feb 19, 2021
b578494
bots_importlib no longer required
Feb 19, 2021
17b838d
remove checks for old python and elementtree
Feb 19, 2021
0e17670
remove try/except imports for old stuff
Feb 20, 2021
40e9009
fixes in inmessage for edifact UNA and CONTRL
Feb 25, 2021
9626ff0
fix nextmessage
Feb 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 58 additions & 31 deletions bots/admin.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
''' Bots configuration for django's admin site.'''
from django import forms
try:
from django.forms import util as django_forms_util
except:
from django.forms import utils as django_forms_util #django1.7
from django.forms import utils as django_forms_util
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
#bots-modules
from . import models
from . import botsglobal

from django.utils.html import format_html
from django.urls import reverse

class BotsAdmin(admin.ModelAdmin):
''' all classes in this module are sub-classed from BotsAdmin.
'''
list_per_page = botsglobal.ini.getint('settings','adminlimit',botsglobal.ini.getint('settings','limit',30))
save_on_top = botsglobal.ini.getboolean('settings','save_on_top',False)
save_as = True
def activate(self, request, queryset):
''' handles the admin 'activate' action.'''
#much faster: queryset.update(active=not F('active')) but negation of F() object is not yet supported in django (20140307)
for obj in queryset:
obj.active = not obj.active
obj.save()
admin.ModelAdmin.log_change(None, request, obj, 'Changed active: %s' %obj.active)
activate.short_description = 'activate/de-activate'

#*****************************************************************************************************
Expand All @@ -34,25 +35,32 @@ class CcodeAdmin(BotsAdmin):
search_fields = ('ccodeid__ccodeid','leftcode','rightcode','attr1','attr2','attr3','attr4','attr5','attr6','attr7','attr8')
fieldsets = (
(None, {'fields': ('ccodeid','leftcode','rightcode','attr1','attr2','attr3','attr4','attr5','attr6','attr7','attr8'),
'description': 'For description of user code lists and usage in mapping: see <a target="_blank" href="<a target="_blank" href="https://botsdocs.readthedocs.io/en/latest/configuration/mapping-scripts/code-conversion.html">documentation</a>.',
'classes': ('wide extrapretty',)
'description': 'For description of user code lists and usage in mapping: see <a target="_blank" href="https://botsdocs.readthedocs.io/en/latest/configuration/mapping-scripts/code-conversion.html">documentation</a>.',
'classes': ('',)
}),
)
def lookup_allowed(self, lookup, *args, **kwargs):
if lookup.startswith('ccodeid'):
return True
return super(CcodeAdmin, self).lookup_allowed(lookup, *args, **kwargs)
def get_form(self, request, obj=None, **kwargs):
# over-ride form text field widths to better fit their actual size
form = super(CcodeAdmin, self).get_form(request, obj, **kwargs)
for field in form.base_fields:
if form.base_fields[field].widget.attrs.get('class') == 'vTextField':
form.base_fields[field].widget.attrs['style'] = 'width: %dch;' %min(70,int(form.base_fields[field].widget.attrs['maxlength']))
return form
admin.site.register(models.ccode,CcodeAdmin)

class CcodetriggerAdmin(BotsAdmin):
list_display = ('ccodeid','ccodeid_desc',)
list_display = ('ccodeid','download','upload','rowcount','ccodeid_desc',)
list_display_links = ('ccodeid',)
ordering = ('ccodeid',)
search_fields = ('ccodeid','ccodeid_desc')
admin.site.register(models.ccodetrigger,CcodetriggerAdmin)

class ChannelAdmin(BotsAdmin):
list_display = ('idchannel', 'inorout', 'type', 'communicationscript', 'remove', 'host', 'port', 'username', 'secret', 'path', 'filename','mdnchannel','testpath','archivepath','rsrv3','rsrv2','rsrv1','syslock','parameters','starttls','apop','askmdn','sendmdn','ftpactive', 'ftpbinary')
list_display = ('idchannel', 'inorout', 'type', 'communicationscript', 'remove', 'host', 'port', 'username', 'path', 'filename','mdnchannel','testpath','archivepath','rsrv3','rsrv2','rsrv1','syslock','parameters','starttls','apop','askmdn','sendmdn','ftpactive', 'ftpbinary')
list_filter = ('inorout','type')
ordering = ('idchannel',)
readonly_fields = ('communicationscript',)
Expand All @@ -65,22 +73,29 @@ class ChannelAdmin(BotsAdmin):
('path','filename'),
('archivepath','rsrv3'),
'desc'),
'classes': ('wide extrapretty',)
'classes': ('',)
}),
('Email specific',{'fields': ('starttls', 'apop', 'askmdn', 'sendmdn' ),
'classes': ('collapse wide extrapretty',)
'classes': ('collapse',)
}),
('FTP specific',{'fields': ('ftpactive', 'ftpbinary', 'ftpaccount' ),
'classes': ('collapse wide extrapretty',)
'classes': ('collapse',)
}),
('Safe writing & file locking',{'fields': ('mdnchannel','syslock', 'lockname'),
'description': 'For more info see <a target="_blank" href="https://botsdocs.readthedocs.io/en/latest/configuration/channel/file-locking.html">documentation</a><br>',
'classes': ('collapse wide extrapretty',)
'classes': ('collapse',)
}),
('Other',{'fields': ('testpath','keyfile','certfile','rsrv2','rsrv1','parameters'),
'classes': ('collapse wide extrapretty',)
'classes': ('collapse',)
}),
)
def get_form(self, request, obj=None, **kwargs):
# over-ride form text field widths to better fit their actual size
form = super(ChannelAdmin, self).get_form(request, obj, **kwargs)
for field in form.base_fields:
if form.base_fields[field].widget.attrs.get('class') == 'vTextField':
form.base_fields[field].widget.attrs['style'] = 'width: %dch;' %min(70,int(form.base_fields[field].widget.attrs['maxlength']))
return form
admin.site.register(models.channel,ChannelAdmin)

class MyConfirmruleAdminForm(forms.ModelForm):
Expand Down Expand Up @@ -118,7 +133,7 @@ class ConfirmruleAdmin(BotsAdmin):
ordering = ('confirmtype','ruletype')
fieldsets = (
(None, {'fields': ('active','negativerule','confirmtype','ruletype','frompartner', 'topartner','idroute','idchannel','messagetype'),
'classes': ('wide extrapretty',)
'classes': ('',)
}),
)
def formfield_for_dbfield(self,db_field,**kwargs):
Expand All @@ -141,22 +156,22 @@ class PartnerAdmin(BotsAdmin):
list_display_links = ('idpartner',)
list_filter = ('active',)
ordering = ('idpartner',)
search_fields = ('idpartner','name','mail','cc','address1','city','countrysubdivision','countrycode','postalcode','attr1','attr2','attr3','attr4','attr5','name1','name2','name3')
search_fields = ('idpartner','name','address1','city','countrysubdivision','countrycode','postalcode','mail','cc','attr1','attr2','attr3','attr4','attr5','name1','name2','name3','desc')
fieldsets = (
(None, {'fields': ('active', ('idpartner', 'name'), ('mail','cc'),'desc',('startdate', 'enddate')),
'classes': ('wide extrapretty',)
'classes': ('',)
}),
('Address',{'fields': ('name1','name2','name3','address1','address2','address3',('postalcode','city'),('countrycode','countrysubdivision'),('phone1','phone2')),
'classes': ('collapse wide extrapretty',)
'classes': ('collapse',)
}),
('Is in groups',{'fields': ('group',),
'classes': ('collapse wide extrapretty',)
'classes': ('collapse',)
}),
('User defined',{'fields': ('attr1','attr2','attr3','attr4','attr5'),
'classes': ('wide extrapretty',)
'classes': ('collapse',)
}),
)
def queryset(self, request):
def get_queryset(self, request):
return self.model.objects.filter(isgroup=False)
admin.site.register(models.partner,PartnerAdmin)

Expand All @@ -177,10 +192,10 @@ class PartnerGroepAdmin(BotsAdmin):
search_fields = ('idpartner','name','desc')
fieldsets = (
(None, {'fields': ('active', 'idpartner', 'name','desc',('startdate', 'enddate')),
'classes': ('wide extrapretty',)
'classes': ('',)
}),
)
def queryset(self, request):
def get_queryset(self, request):
return self.model.objects.filter(isgroup=True)
admin.site.register(models.partnergroep,PartnerGroepAdmin)

Expand All @@ -196,23 +211,35 @@ def clean(self):
return self.cleaned_data

class RoutesAdmin(BotsAdmin):
def fromchannel_link(self, obj):
url = reverse('admin:bots_channel_change', args=(obj.fromchannel_id,))
return format_html("<a href='{}'>{}</a>", url, obj.fromchannel)
fromchannel_link.admin_order_field = 'fromchannel'
fromchannel_link.short_description = 'fromchannel'

def tochannel_link(self, obj):
url = reverse('admin:bots_channel_change', args=(obj.tochannel_id,))
return format_html("<a href='{}'>{}</a>", url, obj.tochannel)
tochannel_link.admin_order_field = 'tochannel'
tochannel_link.short_description = 'tochannel'

actions = ('activate',)
form = MyRouteAdminForm
list_display = ('active','idroute','seq','routescript','fromchannel','fromeditype','frommessagetype','alt','frompartner','topartner','translt','tochannel','defer','toeditype','tomessagetype','frompartner_tochannel','topartner_tochannel','indefaultrun','testindicator','zip_incoming','zip_outgoing',)
list_display = ('active','indefaultrun','idroute','seq','routescript','fromchannel_link','fromeditype','frommessagetype','translt','alt','frompartner','topartner','tochannel_link','defer','toeditype','tomessagetype','frompartner_tochannel','topartner_tochannel','testindicator','zip_incoming','zip_outgoing',)
list_display_links = ('idroute',)
list_filter = ('active','notindefaultrun','idroute','fromeditype')
ordering = ('idroute','seq')
readonly_fields = ('routescript',)
search_fields = ('idroute', 'fromchannel__idchannel','fromeditype', 'frommessagetype', 'alt', 'tochannel__idchannel','toeditype', 'tomessagetype', 'desc')
fieldsets = (
(None, {'fields': (('active','notindefaultrun'),'routescript',('idroute', 'seq',),'fromchannel', ('fromeditype', 'frommessagetype'),'translateind','tochannel','desc'),
'classes': ('wide extrapretty',)
(None, {'fields': (('active','notindefaultrun',),'routescript',('idroute', 'seq',),'fromchannel', ('fromeditype', 'frommessagetype'),'translateind', ('tochannel', 'defer',), 'desc'),
'classes': ('',)
}),
('Filtering for outchannel',{'fields':('toeditype', 'tomessagetype','frompartner_tochannel', 'topartner_tochannel', 'testindicator'),
'classes': ('collapse wide extrapretty',)
'classes': ('collapse',)
}),
('Advanced',{'fields': ('alt','frompartner','topartner','defer','zip_incoming','zip_outgoing'),
'classes': ('collapse wide extrapretty',)
('Advanced',{'fields': ('alt','frompartner','topartner','zip_incoming','zip_outgoing'),
'classes': ('collapse',)
}),
)
admin.site.register(models.routes,RoutesAdmin)
Expand Down Expand Up @@ -243,10 +270,10 @@ class TranslateAdmin(BotsAdmin):
search_fields = ('fromeditype', 'frommessagetype', 'alt', 'frompartner__idpartner', 'topartner__idpartner', 'tscript', 'toeditype', 'tomessagetype', 'desc')
fieldsets = (
(None, {'fields': ('active', ('fromeditype', 'frommessagetype'),'tscript', ('toeditype', 'tomessagetype'),'desc'),
'classes': ('wide extrapretty',)
'classes': ('',)
}),
('Multiple translations per editype/messagetype',{'fields': ('alt', 'frompartner', 'topartner'),
'classes': ('wide extrapretty',)
'classes': ('',)
}),
)
admin.site.register(models.translate,TranslateAdmin)
Expand All @@ -263,7 +290,7 @@ def has_delete_permission(self, request, obj=None): #no deleting of counters
search_fields = ('domein',)
fieldsets = (
(None, {'fields': ('domein', 'nummer'),
'classes': ('wide extrapretty',)
'classes': ('',)
}),
)
admin.site.register(models.uniek,UniekAdmin)
Expand Down
37 changes: 22 additions & 15 deletions bots/automaticmaintenance.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,24 @@ def email_error_report(rootidtaofrun):
break
else:
raise botslib.PanicError('In generate report: could not find report?')
subject = '[Bots Error Report] %(time)s'%{'time':unicode(results['ts'])[:16]}
reporttext = 'Bots Report; type: %(type)s, time: %(time)s\n'%{'type':results['type'],'time':unicode(results['ts'])[:19]}
reporttext += ' %d files received/processed in run.\n'%(results['lastreceived'])
subject = '[Bots Error Report] %(time)s'%{'time':str(results['ts'])[:16]}
reporttext = 'Bots Report; type: %(type)s, time: %(time)s\n'%{'type':results['type'],'time':str(results['ts'])[:19]}
reporttext += pluralize(' %d file%s received/processed in run.\n',results['lastreceived'])
if results['lastdone']:
reporttext += ' %d files without errors,\n'%(results['lastdone'])
reporttext += pluralize(' %d file%s without errors,\n',results['lastdone'])
if results['lasterror']:
subject += '; %d file errors'%(results['lasterror'])
reporttext += ' %d files with errors,\n'%(results['lasterror'])
subject += pluralize('; %d file error%s',results['lasterror'])
reporttext += pluralize(' %d file%s with errors,\n',results['lasterror'])
if results['lastok']:
subject += '; %d files stuck'%(results['lastok'])
reporttext += ' %d files got stuck,\n'%(results['lastok'])
subject += pluralize('; %d file%s stuck',results['lastok'])
reporttext += pluralize(' %d file%s got stuck,\n',results['lastok'])
if results['lastopen']:
subject += '; %d system errors'%(results['lastopen'])
reporttext += ' %d system errors,\n'%(results['lastopen'])
subject += pluralize('; %d system error%s',results['lastopen'])
reporttext += pluralize(' %d system error%s,\n',results['lastopen'])
if results['processerrors']:
subject += '; %d process errors'%(results['processerrors'])
reporttext += ' %d errors in processes.\n'%(results['processerrors'])
reporttext += ' %d files send in run.\n'%(results['send'])
subject += pluralize('; %d process error%s',results['processerrors'])
reporttext += pluralize(' %d process error%s,\n',results['processerrors'])
reporttext += pluralize(' %d file%s sent in run.\n',results['send'])

botsglobal.logger.info(reporttext) #log the report texts
# only send email report if there are errors.
Expand All @@ -113,7 +113,7 @@ def email_error_report(rootidtaofrun):
AND statust=%(statust)s ''',
{'rootidtaofrun':rootidtaofrun,'status':PROCESS,'statust':ERROR}):
reporttext += '\nProcess error:\n'
for key in row.keys():
for key in list(row.keys()):
reporttext += '%s: %s\n' % (key,row[key])
# Include details about file errors in the email report; if debug is True: includes trace
if results['lasterror'] or results['lastopen'] or results['lastok']:
Expand All @@ -123,13 +123,20 @@ def email_error_report(rootidtaofrun):
AND statust!=%(statust)s ''',
{'rootidtaofrun':rootidtaofrun,'statust':DONE}):
reporttext += '\nFile error:\n'
for key in row.keys():
for key in list(row.keys()):
reporttext += '%s: %s\n' % (key,row[key])

botslib.sendbotserrorreport(subject,reporttext)

return int(results['status']) #return report status: 0 (no error) or 1 (error)

def pluralize(text,number):
# simple pluralize function using Django pluralize filter
# handles only the simple case of adding an s, no exceptions are needed here
# input text should contain %d for the number and %s for the plural
# eg. pluralize('%d files%s sent',counter)
from django.template.defaultfilters import pluralize
return text %(number,pluralize(number))

class Trace(object):
''' trace for one incoming file.
Expand Down
1 change: 1 addition & 0 deletions bots/bots_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def set_context(request):
my_context['bots_mindate'] = 0 - botsglobal.ini.getint('settings','maxdays',30)
my_context['menu_automaticretrycommunication'] = botsglobal.ini.getboolean('webserver','menu_automaticretrycommunication',False)
my_context['menu_cleanup'] = botsglobal.ini.getboolean('webserver','menu_cleanup',False)
my_context['menu_changepassword'] = botsglobal.ini.getboolean('webserver','menu_changepassword',True)
#in bots.ini it is possible to add custom menus
if botsglobal.ini.has_section('custommenus'):
my_context['custom_menuname'] = botsglobal.ini.get('custommenus','menuname','Custom')
Expand Down
38 changes: 0 additions & 38 deletions bots/bots_importlib.py

This file was deleted.

Loading